Page MenuHomePhabricator

Sometimes color highlighting doesn't work on differential
Closed, ResolvedPublic

Description

Sometimes when I visit a differential page the color highlighting is
wrong: instead of green and red it's a very light gray. I've only
seen this when viewing a diff where the vs argument is specified.
Here's a specific url I'm seeing it on now:

http://phabricator.khanacademy.org/D2236?vs=1695&id=1707&whitespace=ignore-all#toc

I looked in the javascript console and didn't see any errors there,
but I don't know exactly where to look. It seems like it's most
likely a css issue of some sort, but I'm not good at debugging that
kind of thing.

This is on both firefox and chrome on linux.

My window manager doesn't let me drag and drop, so I can't attach the screenshot I've taken to show the problem, but I've attached the raw page html below. (I tried emailing the bug report, with the attachment, to bugs@phabricator.com, but that didn't seem to work either.)

--cut here--

<!DOCTYPE html><html><head><meta charset="UTF-8" /><title>⚙ D2236 Add in AMBIGUOUS_PLURAL filter and error handling</title><link rel="apple-touch-icon" href="/res/3380adf2/rsrc/image/apple-touch-icon.png" /><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /><script type="text/javascript">(top == self) || top.location.replace(self.location.href);window.DEV=0;</script><link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/pkg/55644450/core.pkg.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/pkg/8aaacd1b/differential.pkg.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/e10bf844/rsrc/css/layout/phabricator-tag-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/f63afae7/rsrc/css/layout/phabricator-action-list-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/a04cc81d/rsrc/css/layout/phabricator-property-list-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/59e4c9b1/rsrc/css/core/spacing.css" />
<style type="text/css">.PhabricatorMonospaced, .phabricator-remarkup .remarkup-code-block { font: 10px "Menlo", "Consolas", "Monaco", monospace; } .platform-windows .PhabricatorMonospaced, .platform-windows .phabricator-remarkup .remarkup-code-block { font: 11px "Menlo", "Consolas", "Monaco", monospace; }</style><script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/7af6987f/rsrc/externals/javelin/core/init.js"></script>
</head><body class="device-desktop platform-linux"><div id="base-page" class="phabricator-standard-page"><div class="phabricator-main-menu" id="UQ0_10"><a class="phabricator-main-menu-expand-button phabricator-expand-search-menu" data-sigil="jx-toggle-class" data-meta="0_30"><span class="phabricator-menu-button-icon sprite-menu menu-icon-app" id="UQ0_14"></span></a><a class="phabricator-main-menu-search-button phabricator-expand-application-menu" data-sigil="jx-toggle-class" data-meta="0_31"><span class="phabricator-menu-button-icon sprite-menu menu-icon-search" id="UQ0_15"></span></a><a class="phabricator-main-menu-logo" href="/"><span class="sprite-menu phabricator-main-menu-logo-image"></span></a><div class="phabricator-main-menu-alerts"><a href="/notification/" class="sprite-menu alert-notifications" id="UQ0_13"><span class="sprite-menu phabricator-main-menu-alert-icon"></span><span id="UQ0_11" class="phabricator-main-menu-alert-count">0</span></a></div><div class="phabricator-menu-view phabricator-dark-menu phabricator-application-menu"><div class="phabricator-menu-item-view phabricator-menu-item-type-label"><span class="phabricator-menu-item-name">User Revisions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/active/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Active</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/revisions/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Revisions</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/reviews/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Reviews</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/subscribed/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Subscribed</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/drafts/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Draft Reviews</span></a><div class="phabricator-menu-item-view phabricator-menu-item-type-label"><span class="phabricator-menu-item-name">All Revisions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/all/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">All</span></a><div class="phabricator-menu-item-view phabricator-menu-item-type-label phabricator-core-item-device"><span class="phabricator-menu-item-name">Actions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="http://www.phabricator.com/docs/phabricator/article/Differential_User_Guide.html"><span class="phabricator-menu-item-icon sprite-icon action-help"></span><span class="phabricator-core-menu-icon sprite-apps-large apps-help-light-large"></span><span class="phabricator-menu-item-name">Differential Help</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-core-menu-item" href="/p/csilvers/"><span class="phabricator-core-menu-icon phabricator-core-menu-profile-image" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png)"></span><span class="phabricator-menu-item-name">csilvers</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-core-menu-item" href="/settings/"><span class="phabricator-menu-item-icon sprite-icon action-settings"></span><span class="phabricator-core-menu-icon sprite-apps-large apps-settings-light-large"></span><span class="phabricator-menu-item-name">Settings</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-menu-item-type-link phabricator-core-menu-item" href="/logout/"><span class="phabricator-core-menu-icon sprite-apps-large apps-power-light-large"></span><span class="phabricator-menu-item-name">Log Out</span></a></div><div class="phabricator-menu-view phabricator-dark-menu phabricator-search-menu"><div class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-main-menu-search"><form action="/search/" method="POST"><input type="hidden" name="csrf" value="7454029d69b7df6c" /><input type="hidden" name="form" value="1" /><div class="phabricator-main-menu-search-container"><input type="text" name="query" id="UQ0_16" autocomplete="off" /><button>Search</button><input type="hidden" name="scope" /><div id="UQ0_17" class="phabricator-main-menu-search-target"></div></div></form></div></div><div id="UQ0_12" class="phabricator-notification-menu" style="display: none;" data-sigil="phabricator-notification-menu"></div></div><div class="phabricator-standard-page-body"><div class="phabricator-nav" id="UQ0_9"><div class="phabricator-nav-content" id="UQ0_8"><div class="phabricator-crumbs-view sprite-gradient gradient-breadcrumbs"><div class="phabricator-crumbs-actions"><a href="/differential/diff/create/" class="phabricator-crumbs-action"><span class="sprite-icon action-create"></span><span class="phabricator-crumbs-action-name">Create Diff</span></a></div><a href="/differential/" class="phabricator-crumb-view phabricator-crumb-has-icon"><span class="phabricator-crumb-icon sprite-apps-large apps-differential-dark-large"></span><span class="phabricator-crumb-name"></span><span class="sprite-menu phabricator-crumb-divider"></span></a><a href="/D2236" class="phabricator-crumb-view phabricator-last-crumb"><span class="phabricator-crumb-name">D2236</span></a></div><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_29"></legend><a name="top" id="top" class="phabricator-anchor-view"></a><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Add in AMBIGUOUS_PLURAL filter and error handling <span class="phabricator-header-tags"><span class="phabricator-tag-view phabricator-tag-type-state"><span class="phabricator-tag-core phabricator-tag-color-orange">Needs Review</span></span></span></h1></div><ul class="phabricator-action-list-view"><li class="phabricator-action-view phabricator-action-view-disabled"><span class="phabricator-action-view-icon sprite-icon action-subscribe-auto-grey"></span><span class="phabricator-action-view-item">Automatically Subscribed</span></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-link"></span><a href="/search/attach/PHID-DREV-ftaoppilysl3ubpczei3/DREV/dependencies/" class="phabricator-action-view-item" data-sigil="workflow">Edit Dependencies</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-attach"></span><a href="/search/attach/PHID-DREV-ftaoppilysl3ubpczei3/TASK/" class="phabricator-action-view-item" data-sigil="workflow">Edit Maniphest Tasks</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-download"></span><a href="/D2236?vs=1695&amp;id=1707&amp;whitespace=ignore-all&amp;download=true" class="phabricator-action-view-item">Download Raw Diff</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-flag-ghost"></span><a href="/flag/edit/PHID-DREV-ftaoppilysl3ubpczei3/" class="phabricator-action-view-item" data-sigil="workflow">Flag For Later</a></li></ul><div class="phabricator-property-list-view"><div class="keyboard-shortcuts-available">Press <strong>?</strong> to show keyboard shortcuts.</div><div class="phabricator-property-list-container"><dl class="phabricator-property-list-properties"><dt class="phabricator-property-list-key">Author</dt><dd class="phabricator-property-list-value"><a href="/p/john/">john</a></dd><dt class="phabricator-property-list-key">Reviewers</dt><dd class="phabricator-property-list-value"><a href="/p/csilvers/">csilvers</a></dd><dt class="phabricator-property-list-key">CCs</dt><dd class="phabricator-property-list-value"><em>None</em></dd><dt class="phabricator-property-list-key">Lint</dt><dd class="phabricator-property-list-value"><table class="differential-results-table" data-sigil="differential-results-table"><tr class="differential-results-row-star"><th><span class="diff-star-skip">★</span></th><td>Lint Skipped</td></tr></table></dd><dt class="phabricator-property-list-key">Unit</dt><dd class="phabricator-property-list-value"><table class="differential-results-table" data-sigil="differential-results-table"><tr class="differential-results-row-star"><th><span class="diff-star-skip">★</span></th><td>Unit Tests Skipped</td></tr></table></dd><dt class="phabricator-property-list-key">Apply Patch</dt><dd class="phabricator-property-list-value"><tt>arc patch D2236</tt></dd></dl><div class="phabriator-property-list-view-end"></div></div></div><div class="differential-primary-pane" id="UQ0_0"><div class="differential-comment-list" id="UQ0_1"><div class="phabricator-transaction-view" id="anchor-summary" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-summarize"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info">Mon, May 6, 4:35 PM · <a name="summary" id="summary" class="phabricator-anchor-view"></a><a href="#summary">D2236#summary</a></span><div><a href="/p/john/">john</a> summarized this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>This adds in a new filter and markup format for plurals. The new format is as such:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="nf" data-symbol-name="item">item</span><span class="o">(</span><span class="mi">1</span><span class="o">),</span> <span class="no">NUM</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>becomes:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="item">item</span><span class="o">(</span><span class="mi">1</span><span class="o">).</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="no">NUM</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>This is possible because all word functions (like <tt>item(1)</tt>) have been modified to add in a <tt>.plural()</tt> function which can handle a number and return the correct plural.</p>

<p>The issue now becomes that there are a number of variables inside exercises where if we converted it directly to this new format it would instantly break the exercise (since those variables don&#039;t have the support baked in). To counteract this I mark up these ambiguous variables using the format:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="AMBIGUOUS_PLURAL">AMBIGUOUS_PLURAL</span><span class="o">(</span><span class="no">TEXT_VAR</span><span class="o">,</span> <span class="no">NUM_VAR</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>And then use the new <tt>AmbiguousPluralFilter</tt> to throw an error if a call to <tt>AMBIGUOUS_PLURAL</tt> exists (this helps to catch function calls that haven&#039;t been converted by the dev yet, using the linter). The dev should go through each file that has one of these <tt>AMBIGUOUS_PLURAL</tt> calls, update the variables to use the new <tt>new Plural</tt> format added to word-problems.js, and THEN modify the function call to look something like:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="no">TEXT_VAR</span><span class="o">.</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="no">NUM_VAR</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>A correctly marked up exercise will look something like this: <a href="https://gist.github.com/jeresig/4b537fe2d11f6cb93e13" target="_blank">https://gist.github.com/jeresig/4b537fe2d11f6cb93e13</a> (note the usage of <tt>new Plural</tt>).</p>

<p>Additionally while I was working on this functionality I found a bug where additional <tt>&lt;span&gt;</tt>s were being inserted incorrectly in some cases (it came up in the new test cases). I fixed this as well.</p></div></div></div></div></div><div class="phabricator-transaction-view" id="anchor-test-plan" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-testplan"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info">Mon, May 6, 4:35 PM · <a name="test-plan" id="test-plan" class="phabricator-anchor-view"></a><a href="#test-plan">D2236#test-plan</a></span><div><a href="/p/john/">john</a> explained the test plan for this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Run <tt>python build/lint_i18n_strings_test.py</tt> and make sure all the tests pass.</p></div></div></div></div></div><div class="phabricator-transaction-view" id="anchor-comment-1" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-none"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info"><span class="phabricator-content-source-view">Via Web</span> · Mon, May 6, 5:55 PM · <a name="comment-1" id="comment-1" class="phabricator-anchor-view"></a><a href="#comment-1">D2236#1</a></span><div><a href="/p/csilvers/">csilvers</a> commented on this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Great commit message! Super-helpful.</p>

<p>I believe this code is correct because of the unittests, but I&#039;m not sure I understand it, so I&#039;m hesitant to approve it until I do.</p></div><div class="phabricator-inline-summary">Inline Comments</div><table class="phabricator-inline-summary-table"><tr><th colspan="3">build/lint_i18n_strings.py</th></tr>
<tr><td class="inline-line-number"><a href="#inline-1064" class="num">1081–1082</a></td><td class="inline-summary-content" colspan="2"><div class="phabricator-remarkup"><p>Did you intend to put a docstring here?</p></div></td></tr>
<tr><td class="inline-line-number"><a href="#inline-1065" class="num">1244–1246</a></td><td class="inline-summary-content" colspan="2"><div class="phabricator-remarkup"><p>I&#039;m confused by this. I thought the point of IS_AMBIGUOUS was for vars that we weren&#039;t sure if it had the .plural() method on it or not. Won&#039;t we know that for all the stuff in _string_vars or _number_vars? I guess I don&#039;t understand what kinds of input will cause _check_plural_is_ambiguous() to return True and what kinds will cause it to return False.</p>

<p>I also don&#039;t really understand what <tt>plural_arg</tt> is. Maybe augment this docstring to give an example value for <tt>plural_arg</tt>, and values for which it would return True or False.</p></div></td></tr></table></div></div></div></div><div class="phabricator-transaction-view" id="anchor-comment-2" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-none"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info"><span class="phabricator-content-source-view">Via Web</span> · Tue, May 7, 8:48 AM · <a name="comment-2" id="comment-2" class="phabricator-anchor-view"></a><a href="#comment-2">D2236#2</a></span><div><a href="/p/john/">john</a> commented on this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Sorry, to clarify a bit: There are two points of ambiguity in <tt>plural()</tt> usage. The first is one that I&#039;ve already fixed: The case where the contents of the variable is unknown (is a string? is it a number?). For this I use a list of built-in known string/number variables and prompt the user for the edge cases.</p>

<p>The second case of ambiguity is knowing if the text contents of a text argument is able to be pluralized, or not. Right now the only case where this is true is for the built-in string functions, like <tt>item(1)</tt>. Pretty much anything else fails this case. I should mention that it&#039;s totally possible that the dev has marked the string up to be pluralizable but we just can&#039;t determine that from our analysis here. The only way we can determine this is to explicitly require the dev to rewrite the function signature to something else. This is why the function call is mutated into the obvious <tt>AMBIGUOUS_PLURAL</tt> and requires that the user manually convert it into the form <tt>TEXT_VAR.plural(NUM_VAR)</tt>. It&#039;s assumed that anything using the new <tt>.plural()</tt> is in fact pluralizable (if it&#039;s not that call is going to throw an exception).</p>

<p>(I&#039;ve essentially copied this comment into the docs for <tt>_check_plural_is_ambiguous</tt>.)</p>

<div id="UQ0_19" style="position: absolute; width: 0; height: 0;"></div>
<script type="text/javascript">JX.Stratcom.mergeData(0, [{"id":"diff-d82d44df","ref":"8204\/8136"},{"id":"diff-f1aba3ab","ref":"8205\/8137"},{"id":"diff-38b2532e","ref":"8206\/8138"},{"id":"diff-b1e586bb","ref":"8207\/8139"},{"anchor":"toc"},{"standaloneURI":"\/differential\/changeset\/?ref=8204%2F8136&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8204%2F8136&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8204%2F8136&whitespace=ignore-all","containerID":"UQ0_4"},{"anchor":"d82d44df"},{"left":"8136","right":"8204"},{"standaloneURI":"\/differential\/changeset\/?ref=8205%2F8137&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8205%2F8137&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8205%2F8137&whitespace=ignore-all","containerID":"UQ0_5"},{"anchor":"f1aba3ab"},{"left":"8137","right":"8205"},{"standaloneURI":"\/differential\/changeset\/?ref=8206%2F8138&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8206%2F8138&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8206%2F8138&whitespace=ignore-all","containerID":"UQ0_6"},{"anchor":"38b2532e"},{"left":"8138","right":"8206"},{"standaloneURI":"\/differential\/changeset\/?ref=8207%2F8139&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8207%2F8139&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8207%2F8139&whitespace=ignore-all","containerID":"UQ0_7"},{"anchor":"b1e586bb"},{"left":"8139","right":"8207"},{"anchor":"comment"},{"action":"b","tip":"Bold"},{"action":"i","tip":"Italics"},{"action":"tt","tip":"Monospaced"},{"action":"ul","tip":"Bulleted List"},{"action":"ol","tip":"Numbered List"},{"action":"code","tip":"Code Block"},{"action":"table","tip":"Table"},{"action":"meme","tip":"Meme"},{"tip":"Help"},{"action":"order","tip":"Order Mode"},{"action":"chaos","tip":"Chaos Mode"},{"anchor":"top"},{"map":{"UQ0_10":"phabricator-application-menu-expanded","UQ0_14":"menu-icon-app-blue"}},{"map":{"UQ0_10":"phabricator-search-menu-expanded","UQ0_15":"menu-icon-search-blue"}}]);
JX.onload(function(){JX.initBehaviors({"refresh-csrf":[{"tokenName":"csrf","header":"X-Phabricator-Csrf","current":"7454029d69b7df6c"}],"history-install":[]})});
JX.onload(function(){JX.initBehaviors({"differential-keyboard-navigation":[{"haunt":"UQ0_0"}],"differential-user-select":[],"phabricator-watch-anchor":[],"differential-diff-radios":[{"radios":["UQ0_2","UQ0_3"]}],"differential-toggle-files":[],"differential-dropdown-menus":[{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}}],"phabricator-oncopy":[],"differential-populate":[{"registry":{"diff-d82d44df":"8204\/8136","diff-f1aba3ab":"8205\/8137","diff-38b2532e":"8206\/8138","diff-b1e586bb":"8207\/8139"},"whitespace":"ignore-all","uri":"\/differential\/changeset\/"}],"differential-show-more":[{"uri":"\/differential\/changeset\/","whitespace":"ignore-all"}],"differential-comment-jump":[],"differential-edit-inline-comments":[{"uri":"\/differential\/comment\/inline\/edit\/2236\/","undo_templates":{"l":"\u003ctable\u003e\u003ctr\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd\u003e\u003cdiv class=\"differential-inline-undo\"\u003eChanges discarded. \u003ca href=\"#\" data-sigil=\"differential-inline-comment-undo\"\u003eUndo\u003c\/a\u003e\u003c\/div\u003e\u003c\/td\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd colspan=\"3\"\u003e\u003c\/td\u003e\u003c\/tr\u003e\u003c\/table\u003e","r":"\u003ctable\u003e\u003ctr\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd\u003e\u003c\/td\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd colspan=\"3\"\u003e\u003cdiv class=\"differential-inline-undo\"\u003eChanges discarded. \u003ca href=\"#\" data-sigil=\"differential-inline-comment-undo\"\u003eUndo\u003c\/a\u003e\u003c\/div\u003e\u003c\/td\u003e\u003c\/tr\u003e\u003c\/table\u003e"},"stage":"differential-review-stage"}],"differential-add-reviewers-and-ccs":[{"dynamic":{"add-reviewers-tokenizer":{"actions":{"request_review":1,"add_reviewers":1},"src":"\/typeahead\/common\/users\/","value":[],"row":"add-reviewers","ondemand":false,"placeholder":"Type a user name..."},"add-ccs-tokenizer":{"actions":{"add_ccs":1},"src":"\/typeahead\/common\/mailable\/","value":[],"row":"add-ccs","ondemand":false,"placeholder":"Type a user or mailing list..."}},"select":"comment-action"}],"differential-accept-with-errors":[{"select":"comment-action","warnings":"warnings"}],"differential-feedback-preview":[{"uri":"\/differential\/comment\/preview\/2236\/","preview":"comment-preview","action":"comment-action","content":"comment-content","previewTokenizers":{"reviewers":"add-reviewers-tokenizer","ccs":"add-ccs-tokenizer"},"inlineuri":"\/differential\/comment\/inline\/preview\/2236\/","inline":"inline-comment-preview"}],"aphront-drag-and-drop-textarea":[{"target":"comment-content","activatedClass":"aphront-textarea-drag-and-drop","uri":"\/file\/dropupload\/"}],"phabricator-remarkup-assist":[],"phabricator-tooltips":[],"workflow":[],"lightbox-attachments":[{"defaultImageUri":"http:\/\/phabricator-files.khanacademy.org\/rsrc\/image\/icon\/fatcow\/document_black.png","downloadForm":"\u003cform action=\"#\" method=\"POST\" class=\"lightbox-download-form\" data-sigil=\"download\"\u003e\u003cinput type=\"hidden\" name=\"csrf\" value=\"7454029d69b7df6c\" \/\u003e\u003cinput type=\"hidden\" name=\"form\" value=\"1\" \/\u003e\u003cbutton\u003eDownload\u003c\/button\u003e\u003c\/form\u003e"}],"aphront-form-disable-on-submit":[],"toggle-class":[],"konami":[],"phabricator-gesture":[],"device":[],"aphlict-dropdown":[{"bubbleID":"UQ0_13","countID":"UQ0_11","dropdownID":"UQ0_12","loadingText":"Loading..."}],"phabricator-keyboard-shortcuts":[{"helpURI":"\/help\/keyboardshortcut\/","searchID":"UQ0_16"}],"phabricator-search-typeahead":[{"id":"UQ0_17","input":"UQ0_16","src":"\/typeahead\/common\/mainsearch\/","limit":10,"placeholder":"Search"}],"aphlict-listen":[{"id":"UQ0_18","containerID":"UQ0_19","server":"phabricator.khanacademy.org","port":"22280","debug":false,"pageObjects":[]}]})});</script></body></html>

Event Timeline

csilvers added a subscriber: csilvers.
<!DOCTYPE html><html><head><meta charset="UTF-8" /><title>⚙ D2236 Add in AMBIGUOUS_PLURAL filter and error handling</title><link rel="apple-touch-icon" href="/res/3380adf2/rsrc/image/apple-touch-icon.png" /><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /><script type="text/javascript">(top == self) || top.location.replace(self.location.href);window.__DEV__=0;</script><link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/pkg/55644450/core.pkg.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/pkg/8aaacd1b/differential.pkg.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/e10bf844/rsrc/css/layout/phabricator-tag-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/f63afae7/rsrc/css/layout/phabricator-action-list-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/a04cc81d/rsrc/css/layout/phabricator-property-list-view.css" />
<link rel="stylesheet" type="text/css" href="http://phabricator-files.khanacademy.org/res/59e4c9b1/rsrc/css/core/spacing.css" />
<style type="text/css">.PhabricatorMonospaced, .phabricator-remarkup .remarkup-code-block { font: 10px "Menlo", "Consolas", "Monaco", monospace; } .platform-windows .PhabricatorMonospaced, .platform-windows .phabricator-remarkup .remarkup-code-block { font: 11px "Menlo", "Consolas", "Monaco", monospace; }</style><script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/7af6987f/rsrc/externals/javelin/core/init.js"></script>
</head><body class="device-desktop platform-linux"><div id="base-page" class="phabricator-standard-page"><div class="phabricator-main-menu" id="UQ0_10"><a class="phabricator-main-menu-expand-button phabricator-expand-search-menu" data-sigil="jx-toggle-class" data-meta="0_30"><span class="phabricator-menu-button-icon sprite-menu menu-icon-app" id="UQ0_14"></span></a><a class="phabricator-main-menu-search-button phabricator-expand-application-menu" data-sigil="jx-toggle-class" data-meta="0_31"><span class="phabricator-menu-button-icon sprite-menu menu-icon-search" id="UQ0_15"></span></a><a class="phabricator-main-menu-logo" href="/"><span class="sprite-menu phabricator-main-menu-logo-image"></span></a><div class="phabricator-main-menu-alerts"><a href="/notification/" class="sprite-menu alert-notifications" id="UQ0_13"><span class="sprite-menu phabricator-main-menu-alert-icon"></span><span id="UQ0_11" class="phabricator-main-menu-alert-count">0</span></a></div><div class="phabricator-menu-view phabricator-dark-menu phabricator-application-menu"><div class="phabricator-menu-item-view phabricator-menu-item-type-label"><span class="phabricator-menu-item-name">User Revisions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/active/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Active</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/revisions/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Revisions</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/reviews/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Reviews</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/subscribed/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Subscribed</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/drafts/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">Draft Reviews</span></a><div class="phabricator-menu-item-view phabricator-menu-item-type-label"><span class="phabricator-menu-item-name">All Revisions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="/differential/filter/all/?vs=1695&amp;id=1707&amp;whitespace=ignore-all"><span class="phabricator-menu-item-name">All</span></a><div class="phabricator-menu-item-view phabricator-menu-item-type-label phabricator-core-item-device"><span class="phabricator-menu-item-name">Actions</span></div><a class="phabricator-menu-item-view phabricator-menu-item-type-link" href="http://www.phabricator.com/docs/phabricator/article/Differential_User_Guide.html"><span class="phabricator-menu-item-icon sprite-icon action-help"></span><span class="phabricator-core-menu-icon sprite-apps-large apps-help-light-large"></span><span class="phabricator-menu-item-name">Differential Help</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-core-menu-item" href="/p/csilvers/"><span class="phabricator-core-menu-icon phabricator-core-menu-profile-image" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png)"></span><span class="phabricator-menu-item-name">csilvers</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-core-menu-item" href="/settings/"><span class="phabricator-menu-item-icon sprite-icon action-settings"></span><span class="phabricator-core-menu-icon sprite-apps-large apps-settings-light-large"></span><span class="phabricator-menu-item-name">Settings</span></a><a class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-menu-item-type-link phabricator-core-menu-item" href="/logout/"><span class="phabricator-core-menu-icon sprite-apps-large apps-power-light-large"></span><span class="phabricator-menu-item-name">Log Out</span></a></div><div class="phabricator-menu-view phabricator-dark-menu phabricator-search-menu"><div class="phabricator-menu-item-view phabricator-menu-item-type-link phabricator-main-menu-search"><form action="/search/" method="POST"><input type="hidden" name="__csrf__" value="7454029d69b7df6c" /><input type="hidden" name="__form__" value="1" /><div class="phabricator-main-menu-search-container"><input type="text" name="query" id="UQ0_16" autocomplete="off" /><button>Search</button><input type="hidden" name="scope" /><div id="UQ0_17" class="phabricator-main-menu-search-target"></div></div></form></div></div><div id="UQ0_12" class="phabricator-notification-menu" style="display: none;" data-sigil="phabricator-notification-menu"></div></div><div class="phabricator-standard-page-body"><div class="phabricator-nav" id="UQ0_9"><div class="phabricator-nav-content" id="UQ0_8"><div class="phabricator-crumbs-view sprite-gradient gradient-breadcrumbs"><div class="phabricator-crumbs-actions"><a href="/differential/diff/create/" class="phabricator-crumbs-action"><span class="sprite-icon action-create"></span><span class="phabricator-crumbs-action-name">Create Diff</span></a></div><a href="/differential/" class="phabricator-crumb-view phabricator-crumb-has-icon"><span class="phabricator-crumb-icon sprite-apps-large apps-differential-dark-large"></span><span class="phabricator-crumb-name"></span><span class="sprite-menu phabricator-crumb-divider"></span></a><a href="/D2236" class="phabricator-crumb-view phabricator-last-crumb"><span class="phabricator-crumb-name">D2236</span></a></div><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_29"></legend><a name="top" id="top" class="phabricator-anchor-view"></a><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Add in AMBIGUOUS_PLURAL filter and error handling <span class="phabricator-header-tags"><span class="phabricator-tag-view phabricator-tag-type-state"><span class="phabricator-tag-core phabricator-tag-color-orange">Needs Review</span></span></span></h1></div><ul class="phabricator-action-list-view"><li class="phabricator-action-view phabricator-action-view-disabled"><span class="phabricator-action-view-icon sprite-icon action-subscribe-auto-grey"></span><span class="phabricator-action-view-item">Automatically Subscribed</span></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-link"></span><a href="/search/attach/PHID-DREV-ftaoppilysl3ubpczei3/DREV/dependencies/" class="phabricator-action-view-item" data-sigil="workflow">Edit Dependencies</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-attach"></span><a href="/search/attach/PHID-DREV-ftaoppilysl3ubpczei3/TASK/" class="phabricator-action-view-item" data-sigil="workflow">Edit Maniphest Tasks</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-download"></span><a href="/D2236?vs=1695&amp;id=1707&amp;whitespace=ignore-all&amp;download=true" class="phabricator-action-view-item">Download Raw Diff</a></li><li class="phabricator-action-view"><span class="phabricator-action-view-icon sprite-icon action-flag-ghost"></span><a href="/flag/edit/PHID-DREV-ftaoppilysl3ubpczei3/" class="phabricator-action-view-item" data-sigil="workflow">Flag For Later</a></li></ul><div class="phabricator-property-list-view"><div class="keyboard-shortcuts-available">Press <strong>?</strong> to show keyboard shortcuts.</div><div class="phabricator-property-list-container"><dl class="phabricator-property-list-properties"><dt class="phabricator-property-list-key">Author</dt><dd class="phabricator-property-list-value"><a href="/p/john/">john</a></dd><dt class="phabricator-property-list-key">Reviewers</dt><dd class="phabricator-property-list-value"><a href="/p/csilvers/">csilvers</a></dd><dt class="phabricator-property-list-key">CCs</dt><dd class="phabricator-property-list-value"><em>None</em></dd><dt class="phabricator-property-list-key">Lint</dt><dd class="phabricator-property-list-value"><table class="differential-results-table" data-sigil="differential-results-table"><tr class="differential-results-row-star"><th><span class="diff-star-skip">★</span></th><td>Lint Skipped</td></tr></table></dd><dt class="phabricator-property-list-key">Unit</dt><dd class="phabricator-property-list-value"><table class="differential-results-table" data-sigil="differential-results-table"><tr class="differential-results-row-star"><th><span class="diff-star-skip">★</span></th><td>Unit Tests Skipped</td></tr></table></dd><dt class="phabricator-property-list-key">Apply Patch</dt><dd class="phabricator-property-list-value"><tt>arc patch D2236</tt></dd></dl><div class="phabriator-property-list-view-end"></div></div></div><div class="differential-primary-pane" id="UQ0_0"><div class="differential-comment-list" id="UQ0_1"><div class="phabricator-transaction-view" id="anchor-summary" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-summarize"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info">Mon, May 6, 4:35 PM · <a name="summary" id="summary" class="phabricator-anchor-view"></a><a href="#summary">D2236#summary</a></span><div><a href="/p/john/">john</a> summarized this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>This adds in a new filter and markup format for plurals. The new format is as such:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="nf" data-symbol-name="item">item</span><span class="o">(</span><span class="mi">1</span><span class="o">),</span> <span class="no">NUM</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>becomes:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="item">item</span><span class="o">(</span><span class="mi">1</span><span class="o">).</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="no">NUM</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>This is possible because all word functions (like <tt>item(1)</tt>) have been modified to add in a <tt>.plural()</tt> function which can handle a number and return the correct plural.</p>

<p>The issue now becomes that there are a number of variables inside exercises where if we converted it directly to this new format it would instantly break the exercise (since those variables don&#039;t have the support baked in). To counteract this I mark up these ambiguous variables using the format:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="nf" data-symbol-name="AMBIGUOUS_PLURAL">AMBIGUOUS_PLURAL</span><span class="o">(</span><span class="no">TEXT_VAR</span><span class="o">,</span> <span class="no">NUM_VAR</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>And then use the new <tt>AmbiguousPluralFilter</tt> to throw an error if a call to <tt>AMBIGUOUS_PLURAL</tt> exists (this helps to catch function calls that haven&#039;t been converted by the dev yet, using the linter). The dev should go through each file that has one of these <tt>AMBIGUOUS_PLURAL</tt> calls, update the variables to use the new <tt>new Plural</tt> format added to word-problems.js, and THEN modify the function call to look something like:</p>

<div class="remarkup-code-block" data-code-lang="php"><pre class="remarkup-code"><span class="o">&lt;</span><span class="k">var</span><span class="o">&gt;</span><span class="no">TEXT_VAR</span><span class="o">.</span><span class="nf" data-symbol-name="plural">plural</span><span class="o">(</span><span class="no">NUM_VAR</span><span class="o">)&lt;/</span><span class="k">var</span><span class="o">&gt;</span></pre></div>

<p>A correctly marked up exercise will look something like this: <a href="https://gist.github.com/jeresig/4b537fe2d11f6cb93e13" target="_blank">https://gist.github.com/jeresig/4b537fe2d11f6cb93e13</a> (note the usage of <tt>new Plural</tt>).</p>

<p>Additionally while I was working on this functionality I found a bug where additional <tt>&lt;span&gt;</tt>s were being inserted incorrectly in some cases (it came up in the new test cases).  I fixed this as well.</p></div></div></div></div></div><div class="phabricator-transaction-view" id="anchor-test-plan" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-testplan"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info">Mon, May 6, 4:35 PM · <a name="test-plan" id="test-plan" class="phabricator-anchor-view"></a><a href="#test-plan">D2236#test-plan</a></span><div><a href="/p/john/">john</a> explained the test plan for this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Run <tt>python build/lint_i18n_strings_test.py</tt> and make sure all the tests pass.</p></div></div></div></div></div><div class="phabricator-transaction-view" id="anchor-comment-1" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-none"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info"><span class="phabricator-content-source-view">Via Web</span> · Mon, May 6, 5:55 PM · <a name="comment-1" id="comment-1" class="phabricator-anchor-view"></a><a href="#comment-1">D2236#1</a></span><div><a href="/p/csilvers/">csilvers</a> commented on this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Great commit message!  Super-helpful.</p>

<p>I believe this code is correct because of the unittests, but I&#039;m not sure I understand it, so I&#039;m hesitant to approve it until I do.</p></div><div class="phabricator-inline-summary">Inline Comments</div><table class="phabricator-inline-summary-table"><tr><th colspan="3">build/lint_i18n_strings.py</th></tr>
<tr><td class="inline-line-number"><a href="#inline-1064" class="num">1081–1082</a></td><td class="inline-summary-content" colspan="2"><div class="phabricator-remarkup"><p>Did you intend to put a docstring here?</p></div></td></tr>
<tr><td class="inline-line-number"><a href="#inline-1065" class="num">1244–1246</a></td><td class="inline-summary-content" colspan="2"><div class="phabricator-remarkup"><p>I&#039;m confused by this.  I thought the point of IS_AMBIGUOUS was for vars that we weren&#039;t sure if it had the .plural() method on it or not.  Won&#039;t we know that for all the stuff in _string_vars or _number_vars?  I guess I don&#039;t understand what kinds of input will cause _check_plural_is_ambiguous() to return True and what kinds will cause it to return False.</p>

<p>I also don&#039;t really understand what <tt>plural_arg</tt> is.  Maybe augment this docstring to give an example value for <tt>plural_arg</tt>, and values for which it would return True or False.</p></div></td></tr></table></div></div></div></div><div class="phabricator-transaction-view" id="anchor-comment-2" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-none"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info"><span class="phabricator-content-source-view">Via Web</span> · Tue, May 7, 8:48 AM · <a name="comment-2" id="comment-2" class="phabricator-anchor-view"></a><a href="#comment-2">D2236#2</a></span><div><a href="/p/john/">john</a> commented on this revision.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Sorry, to clarify a bit: There are two points of ambiguity in <tt>plural()</tt> usage. The first is one that I&#039;ve already fixed: The case where the contents of the variable is unknown (is a string? is it a number?). For this I use a list of built-in known string/number variables and prompt the user for the edge cases.</p>

<p>The second case of ambiguity is knowing if the text contents of a text argument is able to be pluralized, or not. Right now the only case where this is true is for the built-in string functions, like <tt>item(1)</tt>. Pretty much anything else fails this case. I should mention that it&#039;s totally possible that the dev has marked the string up to be pluralizable but we just can&#039;t determine that from our analysis here. The only way we can determine this is to explicitly require the dev to rewrite the function signature to something else. This is why the function call is mutated into the obvious <tt>AMBIGUOUS_PLURAL</tt> and requires that the user manually convert it into the form <tt>TEXT_VAR.plural(NUM_VAR)</tt>. It&#039;s assumed that anything using the new <tt>.plural()</tt> is in fact pluralizable (if it&#039;s not that call is going to throw an exception).</p>

<p>(I&#039;ve essentially copied this comment into the docs for <tt>_check_plural_is_ambiguous</tt>.)</p>

<p>I should note that this change to use the new <tt>.plural()</tt> function removes the need for the <tt>plural_form()</tt> function. (Although we could still have a <tt>plural_form</tt> function that just calls <tt>.plural()</tt>, that&#039;s something that I&#039;ll need to discuss with Eater.)</p></div></div></div></div></div><div class="phabricator-transaction-view" id="anchor-comment-3" style="background-image: url(/res/1c5f2550/rsrc/image/avatar.png);"><div class="phabricator-transaction-detail differential-comment-action-update"><div class="phabricator-transaction-header"><span class="phabricator-transaction-info">Tue, May 7, 8:50 AM · <a name="comment-3" id="comment-3" class="phabricator-anchor-view"></a><a href="#comment-3">D2236#3</a></span><div><a href="/p/john/">john</a> updated this revision to <a href="/D2236?id=1707">Diff #1707</a>.</div></div><div class="phabricator-transaction-content"><div class="differential-comment-core"><div class="phabricator-remarkup"><p>Improve the docs a bit.</p></div></div></div></div></div></div><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Revision Update History</h1></div><div class="differential-revision-history differential-panel"><form action="#toc"><table class="differential-revision-history-table"><tr><th>Diff</th><th>ID</th><th>Base</th><th>Description</th><th>Created</th><th>Lint</th><th>Unit</th></tr>
<tr class="alt"><td class="revhistory-name">Base</td><td class="revhistory-id"><a href="/differential/diff//"></a></td><td class="revhistory-base"></td><td class="revhistory-desc">Base</td><td class="revhistory-age"></td><td class="revhistory-star"></td><td class="revhistory-star"></td><td class="revhistory-old"><input type="radio" name="vs" id="UQ0_2" /></td><td class="revhistory-new"></td></tr>
<tr><td class="revhistory-name">Diff 1</td><td class="revhistory-id"><a href="/differential/diff/1695/">1695</a></td><td class="revhistory-base"></td><td class="revhistory-desc"></td><td class="revhistory-age">Mon, May 6, 4:27 PM</td><td class="revhistory-star" title="Lint Skipped"><span class="diff-star-skip">★</span></td><td class="revhistory-star" title="Unit Tests Skipped"><span class="diff-star-skip">★</span></td><td class="revhistory-old revhistory-old-now"><input type="radio" name="vs" value="1695" id="UQ0_3" checked="checked" /></td><td class="revhistory-new"><input type="radio" name="id" value="1695" data-sigil="differential-new-radio" /></td></tr>
<tr class="alt"><td class="revhistory-name">Diff 2</td><td class="revhistory-id"><a href="/differential/diff/1707/">1707</a></td><td class="revhistory-base"></td><td class="revhistory-desc">Improve the docs a bit.</td><td class="revhistory-age">Tue, May 7, 8:50 AM</td><td class="revhistory-star" title="Lint Skipped"><span class="diff-star-skip">★</span></td><td class="revhistory-star" title="Unit Tests Skipped"><span class="diff-star-skip">★</span></td><td class="revhistory-old"></td><td class="revhistory-new revhistory-new-now"><input type="radio" name="id" value="1707" checked="checked" data-sigil="differential-new-radio" /></td></tr><tr><td colspan="9" class="diff-differ-submit"><label>Whitespace Changes: <select name="whitespace"><option value="ignore-force">Ignore All</option><option value="ignore-all" selected="selected">Ignore Most</option><option value="ignore-trailing">Ignore Trailing</option><option value="show-all">Show All</option></select></label><button>Show Diff</button></td></tr></table></form></div><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_4"></legend><a name="toc" id="toc" class="phabricator-anchor-view"></a><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Table of Contents</h1></div><div class="differential-toc differential-panel"><table><tr><th></th><th></th><th></th><th>Path</th><th class="differential-toc-cov">Coverage (All)</th><th class="differential-toc-mcov">Coverage (Touched)</th></tr><tr><td class="differential-toc-char" title="Modified">M</td><td class="differential-toc-prop"></td><td class="differential-toc-ftype"></td><td class="differential-toc-file"><a href="#d82d44df" data-meta="0_0" data-sigil="differential-load">build/lint_i18n_strings.py</a> (134 lines)</td><td class="differential-toc-cov"><em>-</em></td><td class="differential-toc-mcov"><em>-</em></td></tr>
<tr><td class="differential-toc-char" title="Modified">M</td><td class="differential-toc-prop"></td><td class="differential-toc-ftype"></td><td class="differential-toc-file"><a href="#f1aba3ab" data-meta="0_1" data-sigil="differential-load">build/lint_i18n_strings_test.py</a> (26 lines)</td><td class="differential-toc-cov"><em>-</em></td><td class="differential-toc-mcov"><em>-</em></td></tr>
<tr><td class="differential-toc-char" title="Modified">M</td><td class="differential-toc-prop"></td><td class="differential-toc-ftype"></td><td class="differential-toc-file"><a href="#38b2532e" data-meta="0_2" data-sigil="differential-load">build/lint_test/always_plural_output.html</a> (4 lines)</td><td class="differential-toc-cov"><em>-</em></td><td class="differential-toc-mcov"><em>-</em></td></tr>
<tr><td class="differential-toc-char" title="Modified">M</td><td class="differential-toc-prop"></td><td class="differential-toc-ftype"></td><td class="differential-toc-file"><a href="#b1e586bb" data-meta="0_3" data-sigil="differential-load">build/lint_test/plural_output.html</a> (12 lines)</td><td class="differential-toc-cov"><em>-</em></td><td class="differential-toc-mcov"><em>-</em></td></tr><tr><td colspan="7"><a class="button differential-toc-reveal-all" data-sigil="differential-reveal-all" data-mustcapture="1">Show All Context</a></td></tr></table></div><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Diff 1707</h1></div><div class="differential-review-stage" id="differential-review-stage"><div class="differential-changeset" id="UQ0_4" data-sigil="differential-changeset" data-meta="0_7"><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_6"></legend><a name="d82d44df" id="d82d44df" class="phabricator-anchor-view"></a><div class="differential-changeset-buttons"><a class="button small grey" href="#" target="_blank" data-meta="0_5" data-sigil="differential-view-options">View Options ▼</a></div><h1>build/lint_i18n_strings.py</h1><div style="clear: both"></div><div id="diff-d82d44df"><div class="differential-loading">Loading...</div></div></div><div class="differential-changeset" id="UQ0_5" data-sigil="differential-changeset" data-meta="0_10"><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_9"></legend><a name="f1aba3ab" id="f1aba3ab" class="phabricator-anchor-view"></a><div class="differential-changeset-buttons"><a class="button small grey" href="#" target="_blank" data-meta="0_8" data-sigil="differential-view-options">View Options ▼</a></div><h1>build/lint_i18n_strings_test.py</h1><div style="clear: both"></div><div id="diff-f1aba3ab"><div class="differential-loading">Loading...</div></div></div><div class="differential-changeset" id="UQ0_6" data-sigil="differential-changeset" data-meta="0_13"><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_12"></legend><a name="38b2532e" id="38b2532e" class="phabricator-anchor-view"></a><div class="differential-changeset-buttons"><a class="button small grey" href="#" target="_blank" data-meta="0_11" data-sigil="differential-view-options">View Options ▼</a></div><h1>build/lint_test/always_plural_output.html</h1><div style="clear: both"></div><div id="diff-38b2532e"><div class="differential-loading">Loading...</div></div></div><div class="differential-changeset" id="UQ0_7" data-sigil="differential-changeset" data-meta="0_16"><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_15"></legend><a name="b1e586bb" id="b1e586bb" class="phabricator-anchor-view"></a><div class="differential-changeset-buttons"><a class="button small grey" href="#" target="_blank" data-meta="0_14" data-sigil="differential-view-options">View Options ▼</a></div><h1>build/lint_test/plural_output.html</h1><div style="clear: both"></div><div id="diff-b1e586bb"><div class="differential-loading">Loading...</div></div></div></div><legend class="phabricator-anchor-navigation-marker" data-sigil="marker" data-meta="0_17"></legend><a name="comment" id="comment" class="phabricator-anchor-view"></a><div class="differential-add-comment-panel"><div class="phabricator-header-shell"><h1 class="phabricator-header-view">Leap Into Action</h1></div><form class="phabricator-form-view" action="/differential/comment/save/" method="POST" data-sigil="workflow"><input type="hidden" name="__csrf__" value="7454029d69b7df6c" /><input type="hidden" name="__form__" value="1" /><div class="aphront-form-view"><input type="hidden" name="revision_id" value="2236" /><div class="aphront-form-control aphront-form-control-select"><label class="aphront-form-label">Action</label><div class="aphront-form-input"><select name="action" id="comment-action"><option value="none">Comment</option><option value="accept">Accept Revision ✔</option><option value="reject">Request Changes ✘</option><option value="resign">Resign as Reviewer</option><option value="claim">Commandeer Revision</option><option value="add_reviewers">Add Reviewers</option><option value="add_ccs">Add CCs</option></select></div><div style="clear: both;"></div></div><div class="aphront-form-control aphront-form-control-tokenizer" id="add-reviewers" style="display: none"><label class="aphront-form-label">Add Reviewers</label><div class="aphront-form-input"><div id="add-reviewers-tokenizer" class="jx-tokenizer-container"><input name="reviewers" class="jx-tokenizer-input" style="width: 0px;" disabled="disabled" type="text" data-mustcapture="1" data-sigil="tokenizer-input" /><div style="clear: both;"></div></div></div><div style="clear: both;"></div></div><div class="aphront-form-control aphront-form-control-tokenizer" id="add-ccs" style="display: none"><label class="aphront-form-label">Add CCs</label><div class="aphront-form-input"><div id="add-ccs-tokenizer" class="jx-tokenizer-container"><input name="ccs" class="jx-tokenizer-input" style="width: 0px;" disabled="disabled" type="text" data-mustcapture="1" data-sigil="tokenizer-input" /><div style="clear: both;"></div></div></div><div style="clear: both;"></div></div><div class="aphront-form-control aphront-form-control-textarea"><label class="aphront-form-label">Comment</label><div class="aphront-form-input"><div data-sigil="remarkup-assist-control"><div class="remarkup-assist-bar"><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_18" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-b"></div></a><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_19" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-i"></div></a><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_20" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-tt"></div></a><span class="remarkup-assist-separator"></span><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_21" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-ul"></div></a><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_22" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-ol"></div></a><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_23" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-code"></div></a><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_24" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-table"></div></a><span class="remarkup-assist-separator"></span><a class="remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_25" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-meme"></div></a><a class="remarkup-assist-right remarkup-assist-button" href="http://www.phabricator.com/docs/phabricator/article/Remarkup_Reference.html" target="_blank" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_26"><div class="remarkup-assist sprite-icon remarkup-assist-help"></div></a><span class="remarkup-assist-right remarkup-assist-separator"></span><a class="remarkup-assist-right remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_27" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-order"></div></a><a class="remarkup-assist-right remarkup-assist-button" href="#" tabindex="-1" data-sigil="remarkup-assist has-tooltip" data-meta="0_28" data-mustcapture="1"><div class="remarkup-assist sprite-icon remarkup-assist-chaos"></div></a></div><textarea name="comment" class="remarkup-assist-textarea" id="comment-content"></textarea></div></div><div style="clear: both;"></div></div><div class="aphront-form-control aphront-form-control-submit aphront-form-control-nolabel"><div class="aphront-form-input"><button type="submit" name="__submit__">Clowncopterize</button></div><div style="clear: both;"></div></div></div></form><div id="warnings"><div class="aphront-error-view aphront-error-severity-error"><h1 class="aphront-error-view-head">Lint Skipped</h1><div class="aphront-error-view-body"><p>This diff was created without running lint. Make sure you are OK with that before you accept this diff.</p></div></div><div class="aphront-error-view aphront-error-severity-error"><h1 class="aphront-error-view-head">Unit Tests Skipped</h1><div class="aphront-error-view-body"><p>Unit tests were skipped when this diff was created. Make sure you are OK with that before you accept this diff.</p></div></div></div><div class="aphront-panel-preview aphront-panel-flush"><div id="comment-preview"><span class="aphront-panel-preview-loading-text">Loading comment preview...</span></div><div id="inline-comment-preview"></div></div></div></div></div></div><div style="clear: both;"></div></div></div><script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/pkg/7d174323/javelin.pkg.js"></script>
<script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/pkg/27c55b30/differential.pkg.js"></script>
<script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/pkg/26980a1c/core.pkg.js"></script>
<script type="text/javascript" src="http://phabricator-files.khanacademy.org/res/6c084b09/rsrc/externals/javelin/lib/History.js"></script>

<div id="UQ0_19" style="position: absolute; width: 0; height: 0;"></div>
<script type="text/javascript">JX.Stratcom.mergeData(0, [{"id":"diff-d82d44df","ref":"8204\/8136"},{"id":"diff-f1aba3ab","ref":"8205\/8137"},{"id":"diff-38b2532e","ref":"8206\/8138"},{"id":"diff-b1e586bb","ref":"8207\/8139"},{"anchor":"toc"},{"standaloneURI":"\/differential\/changeset\/?ref=8204%2F8136&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8204%2F8136&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8204%2F8136&whitespace=ignore-all","containerID":"UQ0_4"},{"anchor":"d82d44df"},{"left":"8136","right":"8204"},{"standaloneURI":"\/differential\/changeset\/?ref=8205%2F8137&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8205%2F8137&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8205%2F8137&whitespace=ignore-all","containerID":"UQ0_5"},{"anchor":"f1aba3ab"},{"left":"8137","right":"8205"},{"standaloneURI":"\/differential\/changeset\/?ref=8206%2F8138&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8206%2F8138&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8206%2F8138&whitespace=ignore-all","containerID":"UQ0_6"},{"anchor":"38b2532e"},{"left":"8138","right":"8206"},{"standaloneURI":"\/differential\/changeset\/?ref=8207%2F8139&whitespace=ignore-all","leftURI":"\/differential\/changeset\/?view=old&ref=8207%2F8139&whitespace=ignore-all","rightURI":"\/differential\/changeset\/?view=new&ref=8207%2F8139&whitespace=ignore-all","containerID":"UQ0_7"},{"anchor":"b1e586bb"},{"left":"8139","right":"8207"},{"anchor":"comment"},{"action":"b","tip":"Bold"},{"action":"i","tip":"Italics"},{"action":"tt","tip":"Monospaced"},{"action":"ul","tip":"Bulleted List"},{"action":"ol","tip":"Numbered List"},{"action":"code","tip":"Code Block"},{"action":"table","tip":"Table"},{"action":"meme","tip":"Meme"},{"tip":"Help"},{"action":"order","tip":"Order Mode"},{"action":"chaos","tip":"Chaos Mode"},{"anchor":"top"},{"map":{"UQ0_10":"phabricator-application-menu-expanded","UQ0_14":"menu-icon-app-blue"}},{"map":{"UQ0_10":"phabricator-search-menu-expanded","UQ0_15":"menu-icon-search-blue"}}]);
JX.onload(function(){JX.initBehaviors({"refresh-csrf":[{"tokenName":"__csrf__","header":"X-Phabricator-Csrf","current":"7454029d69b7df6c"}],"history-install":[]})});
JX.onload(function(){JX.initBehaviors({"differential-keyboard-navigation":[{"haunt":"UQ0_0"}],"differential-user-select":[],"phabricator-watch-anchor":[],"differential-diff-radios":[{"radios":["UQ0_2","UQ0_3"]}],"differential-toggle-files":[],"differential-dropdown-menus":[{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}},{"pht":{"Open in Editor":"Open in Editor","Show Entire File":"Show Entire File","Entire File Shown":"Entire File Shown","Can't Toggle Unloaded File":"Can't Toggle Unloaded File","Expand File":"Expand File","Collapse File":"Collapse File","Browse in Diffusion":"Browse in Diffusion","View Standalone":"View Standalone","Show Raw File (Left)":"Show Raw File (Left)","Show Raw File (Right)":"Show Raw File (Right)","Configure Editor":"Configure Editor"}}],"phabricator-oncopy":[],"differential-populate":[{"registry":{"diff-d82d44df":"8204\/8136","diff-f1aba3ab":"8205\/8137","diff-38b2532e":"8206\/8138","diff-b1e586bb":"8207\/8139"},"whitespace":"ignore-all","uri":"\/differential\/changeset\/"}],"differential-show-more":[{"uri":"\/differential\/changeset\/","whitespace":"ignore-all"}],"differential-comment-jump":[],"differential-edit-inline-comments":[{"uri":"\/differential\/comment\/inline\/edit\/2236\/","undo_templates":{"l":"\u003ctable\u003e\u003ctr\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd\u003e\u003cdiv class=\"differential-inline-undo\"\u003eChanges discarded. \u003ca href=\"#\" data-sigil=\"differential-inline-comment-undo\"\u003eUndo\u003c\/a\u003e\u003c\/div\u003e\u003c\/td\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd colspan=\"3\"\u003e\u003c\/td\u003e\u003c\/tr\u003e\u003c\/table\u003e","r":"\u003ctable\u003e\u003ctr\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd\u003e\u003c\/td\u003e\u003cth\u003e\u003c\/th\u003e\u003ctd colspan=\"3\"\u003e\u003cdiv class=\"differential-inline-undo\"\u003eChanges discarded. \u003ca href=\"#\" data-sigil=\"differential-inline-comment-undo\"\u003eUndo\u003c\/a\u003e\u003c\/div\u003e\u003c\/td\u003e\u003c\/tr\u003e\u003c\/table\u003e"},"stage":"differential-review-stage"}],"differential-add-reviewers-and-ccs":[{"dynamic":{"add-reviewers-tokenizer":{"actions":{"request_review":1,"add_reviewers":1},"src":"\/typeahead\/common\/users\/","value":[],"row":"add-reviewers","ondemand":false,"placeholder":"Type a user name..."},"add-ccs-tokenizer":{"actions":{"add_ccs":1},"src":"\/typeahead\/common\/mailable\/","value":[],"row":"add-ccs","ondemand":false,"placeholder":"Type a user or mailing list..."}},"select":"comment-action"}],"differential-accept-with-errors":[{"select":"comment-action","warnings":"warnings"}],"differential-feedback-preview":[{"uri":"\/differential\/comment\/preview\/2236\/","preview":"comment-preview","action":"comment-action","content":"comment-content","previewTokenizers":{"reviewers":"add-reviewers-tokenizer","ccs":"add-ccs-tokenizer"},"inlineuri":"\/differential\/comment\/inline\/preview\/2236\/","inline":"inline-comment-preview"}],"aphront-drag-and-drop-textarea":[{"target":"comment-content","activatedClass":"aphront-textarea-drag-and-drop","uri":"\/file\/dropupload\/"}],"phabricator-remarkup-assist":[],"phabricator-tooltips":[],"workflow":[],"lightbox-attachments":[{"defaultImageUri":"http:\/\/phabricator-files.khanacademy.org\/rsrc\/image\/icon\/fatcow\/document_black.png","downloadForm":"\u003cform action=\"#\" method=\"POST\" class=\"lightbox-download-form\" data-sigil=\"download\"\u003e\u003cinput type=\"hidden\" name=\"__csrf__\" value=\"7454029d69b7df6c\" \/\u003e\u003cinput type=\"hidden\" name=\"__form__\" value=\"1\" \/\u003e\u003cbutton\u003eDownload\u003c\/button\u003e\u003c\/form\u003e"}],"aphront-form-disable-on-submit":[],"toggle-class":[],"konami":[],"phabricator-gesture":[],"device":[],"aphlict-dropdown":[{"bubbleID":"UQ0_13","countID":"UQ0_11","dropdownID":"UQ0_12","loadingText":"Loading..."}],"phabricator-keyboard-shortcuts":[{"helpURI":"\/help\/keyboardshortcut\/","searchID":"UQ0_16"}],"phabricator-search-typeahead":[{"id":"UQ0_17","input":"UQ0_16","src":"\/typeahead\/common\/mainsearch\/","limit":10,"placeholder":"Search"}],"aphlict-listen":[{"id":"UQ0_18","containerID":"UQ0_19","server":"phabricator.khanacademy.org","port":"22280","debug":false,"pageObjects":[]}]})});</script></body></html>

Also, I /think/ this has only happened for differential requests where the user has uploaded a raw diff (rather than using arc diff). So the bug seems to happen when a second raw diff is uploaded to the same differential request, and then I ask to look at a diff of diffs.

Can you "Action -> Upload File" in order to get the screenshot attached?

(Your bugs@ email made it but successfully found a bug, congratulations! One of the students is working in that area of the code right now and we're having some transitional roughness.)

csilvers attached 1 file(s): Restricted File.May 7 2013, 9:17 PM

Aha! Didn't know "Upload File" existed...

I see light green and light red in the screenshot, do you have a weird sort of partial color blindness for red-green pastels maybe? Am I looking at the wrong thing or misunderstanding?

When viewing a diff-of-diffs, we attempt to determine which changes were caused by an intervening rebase (by comparing the left sides of each diff) versus which changes were caused by the author. The rebase changes are highlighted in light red / light green (they are usually not important, but do interact with the diff), while the user changes are highlighted in bolder hues.

So I think what you're seeing is rebase detection? Is this plausible? If so:

  • Are the red and green really indistinguishable? We could introduce a red-green colorblind mode that used orange and blue or something instead.
  • Assuming this is rebase detection, does the detection seem correct (i.e., does knowing what the mechanism is explain the behavior)?

We should communicate this better in any case, but I think it's working as intended.

(Adding an expert on this subject.)

{F42672}

Hmm, I'm not red-green colorblind, but it could just be a problem with my monitor. If I squint really hard, I can see that there's a tiny bit of green in there, but it mostly looks gray. The RGB code that I'm seeing for the "light green" (using xcolorsel) is #f0fff0, which doesn't seem very green to me. And the code I'm seeing for the "light red" is #faf0e6, which likewise isn't very red.

By way of contrast, I'll attach the screenshot for when I'm doing a normal diff of the same code (that is, not a diff-of-diffs, but a diff of the most recently uploaded raw diff against the base).

csilvers attached 1 file(s): Restricted File.May 7 2013, 9:29 PM

To answer your rebase question, there were no intervening rebases in this branch, that I know of, and the diffs in question were definitely made by the author (I showed the lines that the author had changed and wanted me to re-review).

That's not to say that the code didn't detect this as a rebase and use the lighter colors. In fact, it's plausible that's what happened, and it's just that -- perhaps only on my monitor -- the lighter colors are so light I can't really see them.

Can you view "base vs diff 1" and "Download Raw Diff", and then view "base vs diff 2" and "Download Raw Diff", and upload both of them (where diff 1 is whatever's on the left of this issue, and diff 2 is whatever's on the right).

I looked at the html, and the lines in question do indeed seem to be detected as a rebase:

<td class="new-rebase right2" colspan="2">
<span class="sd"> determine that from our analysis here. The only way we can determine this</span>
</td>

Looking in firebug, I see the color code for the background is #eeffee. Is that the intended light-green? If so, and it really does look green to you, it must be an issue with my monitor.

I'll upload the raw diffs as well.

The intended colors are #ffeeee and #eeffee, yeah -- which are faint, but easily distinguishable on my monitor, at least.

csilvers attached 1 file(s): Restricted File.May 7 2013, 9:39 PM
csilvers attached 1 file(s): Restricted File.

Thanks! I think the rebase detection is misfiring here, probably because the diffs are missing context. I'll see if I can narrow that down.

With missing context, we may not have enough information to do rebase detection in general so the easy fix might be to simply disable it.

Macro karlhungus: THAT IS WHY THEY CALL ME I AM EXPERT

#ffeeee is indistinguishable from grey on my monitor on my broken eyes. It's not a big deal; there are no normal grey highlights, and they look different than the other, deeper red

chad claimed this task.

Closing since I don't see anything actionable. Call me, maybe, if I'm wrong.

chad changed the visibility from "All Users" to "Public (No Login Required)".Jan 4 2017, 5:00 PM