From 52e0aa10dfb8c5bb743ee3fcbe25df5b9ce33591 Mon Sep 17 00:00:00 2001 From: Zhizhang Deng Date: Sun, 21 Mar 2021 23:06:24 -0400 Subject: [PATCH 1/3] Added support for opting out endpoint translation Fixed some translation issue Continue to fix some translation problem fix: fixed test cases Fixed all test cases relating to getProblem(s) to adapt new parameter fix: fixed test_leetcode testcase --- lib/commands/list.js | 6 ++++++ lib/commands/show.js | 10 ++++++++-- lib/commands/star.js | 3 ++- lib/commands/submission.js | 10 ++++++++-- lib/commands/submit.js | 3 ++- lib/commands/test.js | 2 +- lib/core.js | 10 +++++----- lib/plugins/cache.js | 8 ++++---- lib/plugins/company.js | 4 ++-- lib/plugins/leetcode.cn.js | 28 ++++++++++++++++++---------- lib/plugins/leetcode.js | 6 +++--- lib/plugins/solution.discuss.js | 4 ++-- test/plugins/test_cache.js | 22 +++++++++++----------- test/plugins/test_leetcode.js | 14 +++++++------- test/test_core.js | 29 +++++++++++++++-------------- 15 files changed, 94 insertions(+), 65 deletions(-) diff --git a/lib/commands/list.js b/lib/commands/list.js index 963284a3..ea0b0a0c 100644 --- a/lib/commands/list.js +++ b/lib/commands/list.js @@ -28,6 +28,12 @@ const cmd = { default: false, describe: 'Show extra details: category, companies, tags.' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', diff --git a/lib/commands/show.js b/lib/commands/show.js index 56b9341e..93f643e2 100644 --- a/lib/commands/show.js +++ b/lib/commands/show.js @@ -57,6 +57,12 @@ const cmd = { default: false, describe: 'Show extra question details in source code' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', @@ -175,7 +181,7 @@ cmd.handler = function(argv) { session.argv = argv; if (argv.keyword.length > 0) { // show specific one - core.getProblem(argv.keyword, function(e, problem) { + core.getProblem(argv.keyword, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); showProblem(problem, argv); }); @@ -194,7 +200,7 @@ cmd.handler = function(argv) { if (problems.length === 0) return log.fail('Problem not found!'); const problem = _.sample(problems); - core.getProblem(problem, function(e, problem) { + core.getProblem(problem, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); showProblem(problem, argv); }); diff --git a/lib/commands/star.js b/lib/commands/star.js index 3660432b..6a396dc9 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -29,7 +29,8 @@ const cmd = { cmd.handler = function(argv) { session.argv = argv; - core.getProblem(argv.keyword, function(e, problem) { + // translation doesn't affect question lookup + core.getProblem(argv.keyword, true, function(e, problem) { if (e) return log.fail(e); core.starProblem(problem, !argv.delete, function(e, starred) { diff --git a/lib/commands/submission.js b/lib/commands/submission.js index de0449a3..547e3061 100644 --- a/lib/commands/submission.js +++ b/lib/commands/submission.js @@ -42,6 +42,12 @@ const cmd = { default: false, describe: 'Show extra question details in submission code' }) + .option('T', { + alias: 'dontTranslate', + type: 'boolean', + default: false, + describe: 'Set to true to disable endpoint\'s translation', + }) .positional('keyword', { type: 'string', default: '', @@ -69,7 +75,7 @@ function doTask(problem, queue, cb) { if (argv.extra) { // have to get problem details, e.g. problem description. - core.getProblem(problem.fid, function(e, problem) { + core.getProblem(problem.fid, !argv.dontTranslate, function(e, problem) { if (e) return cb(e); exportSubmission(problem, argv, onTaskDone); }); @@ -135,7 +141,7 @@ cmd.handler = function(argv) { if (!argv.keyword) return log.fail('missing keyword?'); - core.getProblem(argv.keyword, function(e, problem) { + core.getProblem(argv.keyword, !argv.dontTranslate, function(e, problem) { if (e) return log.fail(e); q.addTask(problem).run(); }); diff --git a/lib/commands/submit.js b/lib/commands/submit.js index 2209249b..c550849b 100644 --- a/lib/commands/submit.js +++ b/lib/commands/submit.js @@ -49,7 +49,8 @@ cmd.handler = function(argv) { const meta = file.meta(argv.filename); - core.getProblem(meta.id, function(e, problem) { + // translation doesn't affect problem lookup + core.getProblem(meta.id, true, function(e, problem) { if (e) return log.fail(e); problem.file = argv.filename; diff --git a/lib/commands/test.js b/lib/commands/test.js index 609a18fd..787d7b57 100644 --- a/lib/commands/test.js +++ b/lib/commands/test.js @@ -60,7 +60,7 @@ function runTest(argv) { const meta = file.meta(argv.filename); - core.getProblem(meta.id, function(e, problem) { + core.getProblem(meta.id, true, function(e, problem) { if (e) return log.fail(e); if (!problem.testable) diff --git a/lib/core.js b/lib/core.js index 5d194e21..c9df6322 100644 --- a/lib/core.js +++ b/lib/core.js @@ -61,7 +61,7 @@ const QUERY_HANDLERS = { }; core.filterProblems = function(opts, cb) { - this.getProblems(function(e, problems) { + this.getProblems(!opts.dontTranslate, function(e, problems) { if (e) return cb(e); for (let q of (opts.query || '').split('')) { @@ -82,11 +82,11 @@ core.filterProblems = function(opts, cb) { }); }; -core.getProblem = function(keyword, cb) { +core.getProblem = function(keyword, needTranslation, cb) { if (keyword.id) - return core.next.getProblem(keyword, cb); + return core.next.getProblem(keyword, needTranslation, cb); - this.getProblems(function(e, problems) { + this.getProblems(needTranslation, function(e, problems) { if (e) return cb(e); keyword = Number(keyword) || keyword; @@ -95,7 +95,7 @@ core.getProblem = function(keyword, cb) { return x.fid + '' === keyword + '' || x.fid + '' === metaFid + '' || x.name === keyword || x.slug === keyword; }); if (!problem) return cb('Problem not found!'); - core.next.getProblem(problem, cb); + core.next.getProblem(problem, needTranslation, cb); }); }; diff --git a/lib/plugins/cache.js b/lib/plugins/cache.js index c224a27e..e3a132c2 100644 --- a/lib/plugins/cache.js +++ b/lib/plugins/cache.js @@ -9,14 +9,14 @@ var session = require('../session'); const plugin = new Plugin(50, 'cache', '', 'Plugin to provide local cache.'); -plugin.getProblems = function(cb) { +plugin.getProblems = function(needTranslation, cb) { const problems = cache.get(h.KEYS.problems); if (problems) { log.debug('cache hit: problems.json'); return cb(null, problems); } - plugin.next.getProblems(function(e, problems) { + plugin.next.getProblems(needTranslation, function(e, problems) { if (e) return cb(e); cache.set(h.KEYS.problems, problems); @@ -24,7 +24,7 @@ plugin.getProblems = function(cb) { }); }; -plugin.getProblem = function(problem, cb) { +plugin.getProblem = function(problem, needTranslation, cb) { const k = h.KEYS.problem(problem); const _problem = cache.get(k); if (_problem) { @@ -42,7 +42,7 @@ plugin.getProblem = function(problem, cb) { } } - plugin.next.getProblem(problem, function(e, _problem) { + plugin.next.getProblem(problem, needTranslation, function(e, _problem) { if (e) return cb(e); plugin.saveProblem(_problem); diff --git a/lib/plugins/company.js b/lib/plugins/company.js index 7959363b..68cd2ac8 100644 --- a/lib/plugins/company.js +++ b/lib/plugins/company.js @@ -1511,8 +1511,8 @@ var TAGS = { '1148': ['math'] }; -plugin.getProblems = function(cb) { - plugin.next.getProblems(function(e, problems) { +plugin.getProblems = function(needTranslation, cb) { + plugin.next.getProblems(needTranslation, function(e, problems) { if (e) return cb(e); problems.forEach(function(problem) { diff --git a/lib/plugins/leetcode.cn.js b/lib/plugins/leetcode.cn.js index 60e620eb..77639c7d 100644 --- a/lib/plugins/leetcode.cn.js +++ b/lib/plugins/leetcode.cn.js @@ -70,21 +70,29 @@ function checkError(e, resp, expectedStatus) { return e; } -plugin.getProblems = function(cb) { - plugin.next.getProblems(function(e, problems) { +// overloading getProblems here to make sure everything related +// to listing out problems can have a chance to be translated. +// NOTE: Details of the problem is translated inside leetcode.js +plugin.getProblems = function (needTranslation, cb) { + plugin.next.getProblems(needTranslation, function(e, problems) { if (e) return cb(e); - plugin.getProblemsTitle(function(e, titles) { - if (e) return cb(e); + if (needTranslation) { + // only translate titles of the list if user requested + plugin.getProblemsTitle(function (e, titles) { + if (e) return cb(e); - problems.forEach(function(problem) { - const title = titles[problem.id]; - if (title) - problem.name = title; - }); + problems.forEach(function (problem) { + const title = titles[problem.id]; + if (title) + problem.name = title; + }); + return cb(null, problems); + }); + } else { return cb(null, problems); - }); + } }); }; diff --git a/lib/plugins/leetcode.js b/lib/plugins/leetcode.js index c66d7cfc..9e810146 100644 --- a/lib/plugins/leetcode.js +++ b/lib/plugins/leetcode.js @@ -54,7 +54,7 @@ plugin.init = function() { config.app = 'leetcode'; }; -plugin.getProblems = function(cb) { +plugin.getProblems = function (needTranslation, cb) { log.debug('running leetcode.getProblems'); let problems = []; const getCategory = function(category, queue, cb) { @@ -117,7 +117,7 @@ plugin.getCategoryProblems = function(category, cb) { }); }; -plugin.getProblem = function(problem, cb) { +plugin.getProblem = function(problem, needTranslation, cb) { log.debug('running leetcode.getProblem'); const user = session.getUser(); if (problem.locked && !user.paid) return cb('failed to load locked problem!'); @@ -161,7 +161,7 @@ plugin.getProblem = function(problem, cb) { problem.likes = q.likes; problem.dislikes = q.dislikes; - problem.desc = q.translatedContent ? q.translatedContent : q.content; + problem.desc = (q.translatedContent && needTranslation) ? q.translatedContent : q.content; problem.templates = JSON.parse(q.codeDefinition); problem.testcase = q.sampleTestCase; diff --git a/lib/plugins/solution.discuss.js b/lib/plugins/solution.discuss.js index a161aa50..d5f07c1f 100644 --- a/lib/plugins/solution.discuss.js +++ b/lib/plugins/solution.discuss.js @@ -71,8 +71,8 @@ function getSolution(problem, lang, cb) { }); } -plugin.getProblem = function(problem, cb) { - plugin.next.getProblem(problem, function(e, problem) { +plugin.getProblem = function(problem, needTranslation, cb) { + plugin.next.getProblem(problem, needTranslation, function(e, problem) { if (e || !session.argv.solution) return cb(e, problem); var lang = session.argv.lang; diff --git a/test/plugins/test_cache.js b/test/plugins/test_cache.js index 4480b192..2b46b22a 100644 --- a/test/plugins/test_cache.js +++ b/test/plugins/test_cache.js @@ -52,7 +52,7 @@ describe('plugin:cache', function() { it('should getProblems w/ cache ok', function(done) { cache.set('problems', PROBLEMS); - plugin.getProblems(function(e, problems) { + plugin.getProblems(false, function(e, problems) { assert.equal(e, null); assert.deepEqual(problems, PROBLEMS); done(); @@ -61,9 +61,9 @@ describe('plugin:cache', function() { it('should getProblems w/o cache ok', function(done) { cache.del('problems'); - next.getProblems = cb => cb(null, PROBLEMS); + next.getProblems = (needT, cb) => cb(null, PROBLEMS); - plugin.getProblems(function(e, problems) { + plugin.getProblems(false, function(e, problems) { assert.equal(e, null); assert.deepEqual(problems, PROBLEMS); done(); @@ -72,9 +72,9 @@ describe('plugin:cache', function() { it('should getProblems w/o cache fail if client error', function(done) { cache.del('problems'); - next.getProblems = cb => cb('client getProblems error'); + next.getProblems = (needT, cb) => cb('client getProblems error'); - plugin.getProblems(function(e, problems) { + plugin.getProblems(false, function(e, problems) { assert.equal(e, 'client getProblems error'); done(); }); @@ -86,7 +86,7 @@ describe('plugin:cache', function() { cache.set('problems', PROBLEMS); cache.set('0.slug0.algorithms', PROBLEMS[0]); - plugin.getProblem(_.clone(PROBLEM), function(e, problem) { + plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) { assert.equal(e, null); assert.deepEqual(problem, PROBLEMS[0]); done(); @@ -96,9 +96,9 @@ describe('plugin:cache', function() { it('should getProblem w/o cache ok', function(done) { cache.set('problems', PROBLEMS); cache.del('0.slug0.algorithms'); - next.getProblem = (problem, cb) => cb(null, PROBLEMS[0]); + next.getProblem = (problem, needT, cb) => cb(null, PROBLEMS[0]); - plugin.getProblem(_.clone(PROBLEM), function(e, problem) { + plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) { assert.equal(e, null); assert.deepEqual(problem, PROBLEMS[0]); done(); @@ -108,9 +108,9 @@ describe('plugin:cache', function() { it('should getProblem fail if client error', function(done) { cache.set('problems', PROBLEMS); cache.del('0.slug0.algorithms'); - next.getProblem = (problem, cb) => cb('client getProblem error'); + next.getProblem = (problem, needT, cb) => cb('client getProblem error'); - plugin.getProblem(_.clone(PROBLEM), function(e, problem) { + plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) { assert.equal(e, 'client getProblem error'); done(); }); @@ -140,7 +140,7 @@ describe('plugin:cache', function() { const ret = plugin.updateProblem(PROBLEMS[0], kv); assert.equal(ret, true); - plugin.getProblems(function(e, problems) { + plugin.getProblems(false, function(e, problems) { assert.equal(e, null); assert.deepEqual(problems, [ {id: 0, fid: 0, name: 'name0', slug: 'slug0', value: 'value00', starred: false, desc: '
', likes: '1', dislikes: '1', category: 'algorithms'},
diff --git a/test/plugins/test_leetcode.js b/test/plugins/test_leetcode.js
index 39a1431e..79887df7 100644
--- a/test/plugins/test_leetcode.js
+++ b/test/plugins/test_leetcode.js
@@ -125,7 +125,7 @@ describe('plugin:leetcode', function() {
         .get('/api/problems/concurrency/')
         .replyWithFile(200, './test/mock/problems.json.20160911');
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e, null);
         assert.equal(problems.length, 377 * 4);
         done();
@@ -149,7 +149,7 @@ describe('plugin:leetcode', function() {
         .get('/api/problems/concurrency/')
         .replyWithFile(200, './test/mock/problems.json.20160911');
 
-      plugin.getProblems(function(e, problems) {
+      plugin.getProblems(false, function(e, problems) {
         assert.equal(e.message, 'unknown error');
         done();
       });
@@ -192,7 +192,7 @@ describe('plugin:leetcode', function() {
         .post('/graphql')
         .replyWithFile(200, './test/mock/find-the-difference.json.20171216');
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.equal(e, null);
         assert.equal(problem.totalAC, '89.7K');
         assert.equal(problem.totalSubmit, '175.7K');
@@ -367,7 +367,7 @@ describe('plugin:leetcode', function() {
     it('should fail if no permission for locked', function(done) {
       PROBLEM.locked = true;
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.equal(e, 'failed to load locked problem!');
         done();
       });
@@ -376,7 +376,7 @@ describe('plugin:leetcode', function() {
     it('should fail if session expired', function(done) {
       nock('https://leetcode.com').post('/graphql').reply(403);
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.equal(e, session.errors.EXPIRED);
         done();
       });
@@ -385,7 +385,7 @@ describe('plugin:leetcode', function() {
     it('should fail if http error', function(done) {
       nock('https://leetcode.com').post('/graphql').reply(500);
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.deepEqual(e, {msg: 'http error', statusCode: 500});
         done();
       });
@@ -394,7 +394,7 @@ describe('plugin:leetcode', function() {
     it('should fail if unknown error', function(done) {
       nock('https://leetcode.com').post('/graphql').replyWithError('unknown error!');
 
-      plugin.getProblem(PROBLEM, function(e, problem) {
+      plugin.getProblem(PROBLEM, false, function(e, problem) {
         assert.equal(e.message, 'unknown error!');
         done();
       });
diff --git a/test/test_core.js b/test/test_core.js
index 195f736a..1c689f52 100644
--- a/test/test_core.js
+++ b/test/test_core.js
@@ -40,8 +40,8 @@ describe('core', function() {
 
   beforeEach(function() {
     next = {};
-    next.getProblems = cb => cb(null, PROBLEMS);
-    next.getProblem = (p, cb) => cb(null, p);
+    next.getProblems = (needTrans, cb) => cb(null, PROBLEMS);
+    next.getProblem = (p, needTrans, cb) => cb(null, p);
 
     core = rewire('../lib/core');
     core.setNext(next);
@@ -68,7 +68,7 @@ describe('core', function() {
       let n = cases.length;
 
       for (let x of cases) {
-        core.filterProblems({query: x[0]}, function(e, problems) {
+        core.filterProblems({query: x[0], dontTranslate: false}, function(e, problems) {
           assert.notExists(e);
           assert.equal(problems.length, x[1].length);
 
@@ -90,7 +90,7 @@ describe('core', function() {
       let n = cases.length;
 
       for (let x of cases) {
-        core.filterProblems({tag: x[0]}, function(e, problems) {
+        core.filterProblems({ tag: x[0], dontTranslate: false}, function(e, problems) {
           assert.notExists(e);
           assert.equal(problems.length, x[1].length);
 
@@ -102,7 +102,7 @@ describe('core', function() {
     });
 
     it('should fail if getProblems error', function(done) {
-      next.getProblems = cb => cb('getProblems error');
+      next.getProblems = (needT, cb) => cb('getProblems error');
       core.filterProblems({}, function(e) {
         assert.equal(e, 'getProblems error');
         done();
@@ -340,8 +340,9 @@ describe('core', function() {
   }); // #exportProblem
 
   describe('#getProblem', function() {
-    it('should get by id ok', function(done) {
-      core.getProblem(0, function(e, problem) {
+    it('should get by id ok', function (done) {
+      // set needTranslate to false here because it's not used anyways
+      core.getProblem(0, false, function(e, problem) {
         assert.notExists(e);
         assert.deepEqual(problem, PROBLEMS[0]);
         done();
@@ -349,7 +350,7 @@ describe('core', function() {
     });
 
     it('should get by key ok', function(done) {
-      core.getProblem('slug0', function(e, problem) {
+      core.getProblem('slug0', false, function(e, problem) {
         assert.notExists(e);
         assert.deepEqual(problem, PROBLEMS[0]);
         done();
@@ -357,23 +358,23 @@ describe('core', function() {
     });
 
     it('should fail if not found', function(done) {
-      core.getProblem(3, function(e, problem) {
+      core.getProblem(3, false, function(e, problem) {
         assert.equal(e, 'Problem not found!');
         done();
       });
     });
 
     it('should fail if client error', function(done) {
-      next.getProblem = (problem, cb) => cb('client getProblem error');
+      next.getProblem = (problem, needT, cb) => cb('client getProblem error');
 
-      core.getProblem(0, function(e, problem) {
+      core.getProblem(0, false, function(e, problem) {
         assert.equal(e, 'client getProblem error');
         done();
       });
     });
 
     it('should ok if problem is already there', function(done) {
-      core.getProblem(PROBLEMS[1], function(e, problem) {
+      core.getProblem(PROBLEMS[1], false, function(e, problem) {
         assert.notExists(e);
         assert.deepEqual(problem, PROBLEMS[1]);
         done();
@@ -381,9 +382,9 @@ describe('core', function() {
     });
 
     it('should fail if getProblems error', function(done) {
-      next.getProblems = cb => cb('getProblems error');
+      next.getProblems = (needT, cb) => cb('getProblems error');
 
-      core.getProblem(0, function(e, problem) {
+      core.getProblem(0, false, function(e, problem) {
         assert.equal(e, 'getProblems error');
         done();
       });

From d845e0013f3a8ea827b250e2d07b3498978a2c5f Mon Sep 17 00:00:00 2001
From: Zhizhang Deng 
Date: Tue, 30 Mar 2021 15:41:12 -0400
Subject: [PATCH 2/3] feature: Automatically clear cache when -T changed

---
 lib/cache.js         |  6 ++++++
 lib/helper.js        | 11 ++++++-----
 lib/plugins/cache.js | 19 +++++++++++++++++--
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/lib/cache.js b/lib/cache.js
index 42efad0b..dc10d52e 100644
--- a/lib/cache.js
+++ b/lib/cache.js
@@ -9,6 +9,12 @@ cache.init = function() {
   file.mkdir(file.cacheDir());
 };
 
+cache.deleteAll = function () {
+  cache.list().forEach(value => {
+    cache.del(value.name);
+  })
+};
+
 cache.get = function(k) {
   const fullpath = file.cacheFile(k);
   if (!file.exist(fullpath)) return null;
diff --git a/lib/helper.js b/lib/helper.js
index d256103e..9c5ff43f 100644
--- a/lib/helper.js
+++ b/lib/helper.js
@@ -52,11 +52,12 @@ const LANGS = [
 const h = {};
 
 h.KEYS = {
-  user:     '../user',
-  stat:     '../stat',
-  plugins:  '../../plugins',
-  problems: 'problems',
-  problem:  p => p.fid + '.' + p.slug + '.' + p.category
+  user:        '../user',
+  stat:        '../stat',
+  plugins:     '../../plugins',
+  problems:    'problems',
+  translation: 'translationConfig',
+  problem:     p => p.fid + '.' + p.slug + '.' + p.category
 };
 
 h.prettyState = function(state) {
diff --git a/lib/plugins/cache.js b/lib/plugins/cache.js
index e3a132c2..d6316861 100644
--- a/lib/plugins/cache.js
+++ b/lib/plugins/cache.js
@@ -9,7 +9,21 @@ var session = require('../session');
 
 const plugin = new Plugin(50, 'cache', '', 'Plugin to provide local cache.');
 
-plugin.getProblems = function(needTranslation, cb) {
+// this function will clear all caches if needTranslation is different than stored
+// it will also store the new needTranslation into cache automatically
+function clearCacheIfTchanged(needTranslation) {
+  const translationConfig = cache.get(h.KEYS.translation);
+  if (!translationConfig || translationConfig['useEndpointTranslation'] != needTranslation) {
+    // cache doesn't have the key => old cache version, need to update
+    // or cache does have the key but it contains a different value
+    cache.deleteAll();
+    cache.set(h.KEYS.translation, { useEndpointTranslation: needTranslation });
+    log.debug('cache cleared: -T option changed');
+  }
+}
+
+plugin.getProblems = function (needTranslation, cb) {
+  clearCacheIfTchanged(needTranslation);
   const problems = cache.get(h.KEYS.problems);
   if (problems) {
     log.debug('cache hit: problems.json');
@@ -24,7 +38,8 @@ plugin.getProblems = function(needTranslation, cb) {
   });
 };
 
-plugin.getProblem = function(problem, needTranslation, cb) {
+plugin.getProblem = function (problem, needTranslation, cb) {
+  clearCacheIfTchanged(needTranslation);
   const k = h.KEYS.problem(problem);
   const _problem = cache.get(k);
   if (_problem) {

From e61070db4e587d8298ed2a11de8a435d53ef9d94 Mon Sep 17 00:00:00 2001
From: Zhizhang Deng 
Date: Tue, 30 Mar 2021 20:44:04 -0400
Subject: [PATCH 3/3] fix: cache test cases

---
 test/plugins/test_cache.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/test/plugins/test_cache.js b/test/plugins/test_cache.js
index 2b46b22a..0009c317 100644
--- a/test/plugins/test_cache.js
+++ b/test/plugins/test_cache.js
@@ -19,6 +19,7 @@ describe('plugin:cache', function() {
     {id: 0, fid: 0, name: 'name0', slug: 'slug0', starred: false, desc: '
', likes: '1', dislikes: '1', category: 'algorithms'},
     {id: 1, fid: 1, name: 'name1', slug: 'slug1', starred: true, desc: '
', likes: '1', dislikes: '1', category: 'algorithms'}
   ];
+  const TRANSLATION_CONFIGS = { useEndpointTranslation: false };
   const PROBLEM = {id: 0, fid: 0, slug: 'slug0', category: 'algorithms'};
 
   before(function() {
@@ -51,6 +52,7 @@ describe('plugin:cache', function() {
   describe('#getProblems', function() {
     it('should getProblems w/ cache ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
 
       plugin.getProblems(false, function(e, problems) {
         assert.equal(e, null);
@@ -84,6 +86,7 @@ describe('plugin:cache', function() {
   describe('#getProblem', function() {
     it('should getProblem w/ cache ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
       cache.set('0.slug0.algorithms', PROBLEMS[0]);
 
       plugin.getProblem(_.clone(PROBLEM), false, function(e, problem) {
@@ -135,6 +138,7 @@ describe('plugin:cache', function() {
   describe('#updateProblem', function() {
     it('should updateProblem ok', function(done) {
       cache.set('problems', PROBLEMS);
+      cache.set(h.KEYS.translation, TRANSLATION_CONFIGS);
 
       const kv = {value: 'value00'};
       const ret = plugin.updateProblem(PROBLEMS[0], kv);