You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/12/28 14:47:41 UTC

[apisix-dashboard] branch master updated: feat: improve upstream i18n (#1097)

This is an automated email from the ASF dual-hosted git repository.

juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 2f112ff  feat: improve upstream i18n (#1097)
2f112ff is described below

commit 2f112ffcb4942a392c3a21acece5a712a5d5c1ab
Author: guoqqqi <72...@users.noreply.github.com>
AuthorDate: Mon Dec 28 22:47:29 2020 +0800

    feat: improve upstream i18n (#1097)
    
    * feat: "upstream" i18n
    
    * feat: "menu" i18n
    
    * feat: "button" i18n
    
    * fix: 'query' button for 'search'
    
    * fix: e2e text
    
    * fix: i18n
    
    * fix: i18n
    
    * Update web/src/components/RightContent/AvatarDropdown.tsx
    
    * Update web/src/locales/en-US/menu.ts
    
    * Update web/src/locales/zh-CN/menu.ts
    
    * style: format codes (#1)
    
    Co-authored-by: 琚致远 <ju...@apache.org>
    Co-authored-by: liuxiran <be...@126.com>
---
 web/cypress.json                                   |   8 +-
 web/cypress/fixtures/certificate.json              |  18 +-
 .../consumer/create_and_delete_consumer.spec.js    |  30 +--
 .../integration/metrics/metrics-smoketest.spec.js  |  10 +-
 .../route/create-and-delete-route.spec.js          |  20 +-
 .../settings/settings-smoketest.spec.js            |  14 +-
 web/cypress/integration/ssl/ssl-smoketest.spec.js  |  11 +-
 .../upstream/create_and_delete_upstream.spec.js    |  14 +-
 web/cypress/integration/user/login.spec.js         |   4 +-
 web/cypress/integration/user/logout.spec.js        |   6 +-
 web/cypress/plugins/index.js                       |   2 +-
 web/cypress/support/commands.js                    |  25 +--
 web/cypress/support/index.js                       |   6 +-
 web/src/components/Plugin/PluginPage.tsx           |   6 +-
 web/src/components/RightContent/AvatarDropdown.tsx |  11 +-
 web/src/components/Upstream/UpstreamForm.tsx       | 223 +++++++++++++--------
 web/src/helpers.tsx                                |  16 +-
 web/src/locales/en-US/component.ts                 |   2 +
 web/src/locales/en-US/menu.ts                      |   1 -
 web/src/locales/zh-CN/component.ts                 |   2 +
 web/src/locales/zh-CN/menu.ts                      |   1 -
 web/src/pages/Consumer/List.tsx                    |   4 +
 web/src/pages/Route/Create.tsx                     |  11 +-
 web/src/pages/Route/List.tsx                       |  26 ++-
 .../Route/components/DebugViews/DebugDrawView.tsx  |   2 +-
 .../pages/Route/components/Step1/LabelsDrawer.tsx  |   8 +-
 web/src/pages/Route/components/Step1/MetaView.tsx  |   2 +-
 .../Route/components/Step1/RequestConfigView.tsx   |  21 +-
 web/src/pages/Route/constants.ts                   |   5 +-
 web/src/pages/Route/service.ts                     |  10 +-
 web/src/pages/Route/transform.ts                   |  12 +-
 web/src/pages/Route/typing.d.ts                    |  10 +-
 web/src/pages/SSL/List.tsx                         |   4 +
 web/src/pages/ServerInfo/List.tsx                  |   2 +-
 web/src/pages/ServerInfo/service.ts                |   6 +-
 web/src/pages/Service/Create.tsx                   |  81 ++++----
 web/src/pages/Service/List.tsx                     |  41 ++--
 web/src/pages/Service/components/Step1.tsx         |  46 ++---
 web/src/pages/Service/locales/en-US.ts             |   8 +-
 web/src/pages/Service/locales/zh-CN.ts             |   8 +-
 web/src/pages/Service/service.ts                   |   5 +-
 web/src/pages/Service/typing.d.ts                  |  51 +++--
 web/src/pages/Upstream/Create.tsx                  |  12 +-
 web/src/pages/Upstream/List.tsx                    |  28 +--
 web/src/pages/Upstream/components/Step1.tsx        |  10 +-
 web/src/pages/Upstream/locales/en-US.ts            | 155 +++++++-------
 web/src/pages/Upstream/locales/zh-CN.ts            | 154 +++++++-------
 47 files changed, 627 insertions(+), 525 deletions(-)

diff --git a/web/cypress.json b/web/cypress.json
index a326fda..b937532 100644
--- a/web/cypress.json
+++ b/web/cypress.json
@@ -1,6 +1,6 @@
 {
-    "viewportWidth": 1920,
-    "viewportHeight": 1080,
-    "baseUrl": "http://localhost:8000",
-    "video": false
+  "viewportWidth": 1920,
+  "viewportHeight": 1080,
+  "baseUrl": "http://localhost:8000",
+  "video": false
 }
diff --git a/web/cypress/fixtures/certificate.json b/web/cypress/fixtures/certificate.json
index a7a36d7..b29126e 100644
--- a/web/cypress/fixtures/certificate.json
+++ b/web/cypress/fixtures/certificate.json
@@ -1,11 +1,11 @@
 {
-	"valid": {
-		"cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\nDAtGaXNoZHJvd25lZDEcMBoGA1UEAwwTRmlzaGRyb3duZWQgUk9PVCBDQTAeFw0y\nMDExMDYwOTQ3NDhaFw0yMjExMDYwOTQ3NDhaMH8xCzAJBgNVBAYTAkNOMRIwEAYD\nVQQIDAlHdWFuZ2RvbmcxEjAQBgNVBAcMCUd1YW5nemhvdTEUMBIGA1UECgwLRmlz\naGRyb3duZWQxFzAVBgNVBAsMDnd3dy50ZXN0aGouY29tMRkwFwYDVQQDDBAqLnd3\ndy50ZXN0aGouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC [...]
-		"key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\nSNuPm73C26R6en/Jgu8I09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1\nSLI503ZK2hVH6FdSntBSYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5Y\nRkZdtLCx/rbXPnYLruhG/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poM\nNPcEWic05hBJhpxlDNllwmUpcLEI3orAfbZnBwIDAQABAoIBAQCGvLCMP3iB0oOW\nLC4pAwelpuV+8d/MhOjajurCmEoKqMSs+K2roHVPKPt1uhMeeh4q+ [...]
-		"sni": "*.www.testhj.com"
-	},
-	"invalid": {
-		"cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\n-----END CERTIFICATE-----",
-		"key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\n-----END RSA PRIVATE KEY-----"
-	}
+  "valid": {
+    "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\nDAtGaXNoZHJvd25lZDEcMBoGA1UEAwwTRmlzaGRyb3duZWQgUk9PVCBDQTAeFw0y\nMDExMDYwOTQ3NDhaFw0yMjExMDYwOTQ3NDhaMH8xCzAJBgNVBAYTAkNOMRIwEAYD\nVQQIDAlHdWFuZ2RvbmcxEjAQBgNVBAcMCUd1YW5nemhvdTEUMBIGA1UECgwLRmlz\naGRyb3duZWQxFzAVBgNVBAsMDnd3dy50ZXN0aGouY29tMRkwFwYDVQQDDBAqLnd3\ndy50ZXN0aGouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg [...]
+    "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\nSNuPm73C26R6en/Jgu8I09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1\nSLI503ZK2hVH6FdSntBSYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5Y\nRkZdtLCx/rbXPnYLruhG/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poM\nNPcEWic05hBJhpxlDNllwmUpcLEI3orAfbZnBwIDAQABAoIBAQCGvLCMP3iB0oOW\nLC4pAwelpuV+8d/MhOjajurCmEoKqMSs+K2roHVPKPt1uhMeeh4 [...]
+    "sni": "*.www.testhj.com"
+  },
+  "invalid": {
+    "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\n-----END CERTIFICATE-----",
+    "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\n-----END RSA PRIVATE KEY-----"
+  }
 }
diff --git a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js
index bae929d..e434df7 100644
--- a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js
+++ b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js
@@ -21,13 +21,13 @@ context('Create and Delete Consumer', () => {
   const sleepTime = 100;
   const domSelectors = {
     notification: '.ant-notification-notice-message',
-    pluginsCard: '.ant-card'
+    pluginsCard: '.ant-card',
   };
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
-  })
+  });
 
   it('creates consumer with key-auth', () => {
     // go to consumer create page
@@ -45,14 +45,16 @@ context('Create and Delete Consumer', () => {
     // plugin config
     cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => {
       cy.get('button').first().click();
-    })
+    });
     // edit codemirror
     cy.get('.CodeMirror')
       .first()
       .then((editor) => {
-        editor[0].CodeMirror.setValue(JSON.stringify({
-          "key": "test"
-        }));
+        editor[0].CodeMirror.setValue(
+          JSON.stringify({
+            key: 'test',
+          }),
+        );
         cy.contains('button', 'Submit').click();
       });
     cy.contains('button', 'Next').click();
@@ -64,7 +66,7 @@ context('Create and Delete Consumer', () => {
   it('delete the consumer', () => {
     cy.visit('/');
     cy.contains('Consumer').click();
-    cy.wait(sleepTime * 5)
+    cy.wait(sleepTime * 5);
     cy.contains(name).siblings().contains('Delete').click();
     cy.contains('button', 'Confirm').click();
     cy.get(domSelectors.notification).should('contain', 'Delete Consumer Successfully');
@@ -86,16 +88,18 @@ context('Create and Delete Consumer', () => {
     // plugin config
     cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => {
       cy.get('button').first().click();
-    })
+    });
     // edit codeMirror
     cy.get('.CodeMirror')
       .first()
       .then((editor) => {
-        editor[0].CodeMirror.setValue(JSON.stringify({
-          "key_not_exst": "test"
-        }));
+        editor[0].CodeMirror.setValue(
+          JSON.stringify({
+            key_not_exst: 'test',
+          }),
+        );
         cy.contains('button', 'Submit').click();
       });
     cy.get(domSelectors.notification).should('contain', 'Invalid plugin data');
   });
-})
+});
diff --git a/web/cypress/integration/metrics/metrics-smoketest.spec.js b/web/cypress/integration/metrics/metrics-smoketest.spec.js
index 21ed446..cd10c4a 100644
--- a/web/cypress/integration/metrics/metrics-smoketest.spec.js
+++ b/web/cypress/integration/metrics/metrics-smoketest.spec.js
@@ -18,13 +18,13 @@
 
 context('metrics page smoke test', () => {
   const domSelectors = {
-    pageContent: '.ant-pro-page-container'
+    pageContent: '.ant-pro-page-container',
   };
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
-  })
+  });
 
   it('visit metrics page', () => {
     // go to metrics page
@@ -36,6 +36,6 @@ context('metrics page smoke test', () => {
       .children()
       .should('contain', 'Metrics')
       .and('contain', 'You have not configured Grafana')
-      .and('contain', 'Configure Now')
+      .and('contain', 'Configure Now');
   });
-})
+});
diff --git a/web/cypress/integration/route/create-and-delete-route.spec.js b/web/cypress/integration/route/create-and-delete-route.spec.js
index c8bd6d9..f7fa054 100644
--- a/web/cypress/integration/route/create-and-delete-route.spec.js
+++ b/web/cypress/integration/route/create-and-delete-route.spec.js
@@ -20,9 +20,9 @@ context('Create and Delete Route', () => {
   const name = `routeName${new Date().valueOf()}`;
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
-  })
+  });
 
   it('create route', () => {
     //  go to route create page
@@ -41,9 +41,13 @@ context('Create and Delete Route', () => {
     cy.get('#remote_addrs_0').type('12.12.12.12');
     cy.get('[data-cy=addRemoteAddr]').click();
     cy.get('#remote_addrs_1').type('10.10.10.10');
-    cy.contains('Advanced Routing Matching Conditions').parent().siblings().contains('Create').click();
+    cy.contains('Advanced Routing Matching Conditions')
+      .parent()
+      .siblings()
+      .contains('Create')
+      .click();
 
-    // create Advanced Routing Matching Conditions 
+    // create Advanced Routing Matching Conditions
     cy.get('#position').click();
     cy.contains('Cookie').click();
     cy.get('.ant-modal').within(() => {
@@ -56,7 +60,7 @@ context('Create and Delete Route', () => {
 
     // go to step2
     cy.contains('Next').click();
-    cy.get('#nodes_0_host').type('12.12.12.12')
+    cy.get('#nodes_0_host').type('12.12.12.12');
 
     // go to step3
     cy.contains('Next').click();
@@ -80,9 +84,9 @@ context('Create and Delete Route', () => {
   it('delete the route', () => {
     cy.visit('/routes/list');
     cy.get('[title=Name]').type(name);
-    cy.contains('查 询').click();
+    cy.contains('Search').click();
     cy.contains(name).siblings().contains('Delete').click();
     cy.contains('button', 'Confirm').click();
     cy.get('.ant-notification-notice-message').should('contain', 'Delete Route Successfully');
-  })
-})
+  });
+});
diff --git a/web/cypress/integration/settings/settings-smoketest.spec.js b/web/cypress/integration/settings/settings-smoketest.spec.js
index 77b3676..a6b1e0c 100644
--- a/web/cypress/integration/settings/settings-smoketest.spec.js
+++ b/web/cypress/integration/settings/settings-smoketest.spec.js
@@ -19,13 +19,13 @@
 context('settings page smoke test', () => {
   const domSelectors = {
     pageContent: '.ant-pro-page-container',
-    notificationMsg: '.ant-notification-notice-message'
+    notificationMsg: '.ant-notification-notice-message',
   };
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
-  })
+  });
 
   it('should visit settings page', () => {
     // go to settings page
@@ -37,7 +37,7 @@ context('settings page smoke test', () => {
       .children()
       .should('contain', 'Setting')
       .and('contain', 'Grafana Address')
-      .and('contain', 'Grafana address should begin with HTTP or HTTPS')
+      .and('contain', 'Grafana address should begin with HTTP or HTTPS');
   });
 
   it('should set a invaild url', () => {
@@ -58,8 +58,6 @@ context('settings page smoke test', () => {
     cy.contains('Submit').click();
     cy.get(domSelectors.notificationMsg).should('contain', 'Update Configuration Successfully');
     cy.wait(1000);
-    cy.get(domSelectors.pageContent)
-      .children()
-      .should('contain', 'Metrics')
+    cy.get(domSelectors.pageContent).children().should('contain', 'Metrics');
   });
-})
+});
diff --git a/web/cypress/integration/ssl/ssl-smoketest.spec.js b/web/cypress/integration/ssl/ssl-smoketest.spec.js
index 307bb3b..f0bc964 100644
--- a/web/cypress/integration/ssl/ssl-smoketest.spec.js
+++ b/web/cypress/integration/ssl/ssl-smoketest.spec.js
@@ -19,16 +19,17 @@
 context('ssl smoke test', () => {
   const domSelectors = {
     notificationDesc: '.ant-notification-notice-description',
-    notificationMsg: '.ant-notification-notice-message'
+    notificationMsg: '.ant-notification-notice-message',
   };
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
     cy.fixture('certificate.json').as('certificate');
-  })
+  });
 
-  it('should set match certificate and key by input', function () { // use `function () if used `fixture` above` 
+  it('should set match certificate and key by input', function () {
+    // use `function () if used `fixture` above`
     // go to ssl create page
     cy.visit('/');
     cy.contains('SSL').click();
@@ -72,4 +73,4 @@ context('ssl smoke test', () => {
     cy.wait(100);
     cy.get(domSelectors.notificationDesc).should('contain', "key and cert don't match");
   });
-})
+});
diff --git a/web/cypress/integration/upstream/create_and_delete_upstream.spec.js b/web/cypress/integration/upstream/create_and_delete_upstream.spec.js
index f6e73ea..1822a38 100644
--- a/web/cypress/integration/upstream/create_and_delete_upstream.spec.js
+++ b/web/cypress/integration/upstream/create_and_delete_upstream.spec.js
@@ -20,13 +20,13 @@ context('Create and Delete Upstream', () => {
   const name = `upstreamName${new Date().valueOf()}`;
   const sleepTime = 100; // the unit is milliseconds
   const domSelectors = {
-    notification: '.ant-notification-notice-message'
+    notification: '.ant-notification-notice-message',
   };
 
   beforeEach(() => {
-    // init login 
+    // init login
     cy.login();
-  })
+  });
 
   it('should create upstream with default type (roundrobin)', () => {
     // go to upstream create page
@@ -53,7 +53,7 @@ context('Create and Delete Upstream', () => {
   it('should delete the upstream', () => {
     cy.visit('/');
     cy.contains('Upstream').click();
-    cy.wait(sleepTime * 5)
+    cy.wait(sleepTime * 5);
     cy.contains(name).siblings().contains('Delete').click();
     cy.contains('button', 'Confirm').click();
     cy.get(domSelectors.notification).should('contain', 'Delete successfully');
@@ -79,7 +79,9 @@ context('Create and Delete Upstream', () => {
     cy.get('.ant-select-item-option-active:nth-child(1) > .ant-select-item-option-content').click();
     cy.get('#key').click();
     cy.wait(sleepTime);
-    cy.get('div:nth-child(8) .ant-select-item:nth-child(1) > .ant-select-item-option-content:nth-child(1)').click();
+    cy.get(
+      'div:nth-child(8) .ant-select-item:nth-child(1) > .ant-select-item-option-content:nth-child(1)',
+    ).click();
 
     // add first upstream node
     cy.get('#nodes_0_host').type('127.0.0.1');
@@ -107,4 +109,4 @@ context('Create and Delete Upstream', () => {
     cy.contains('button', 'Confirm').click();
     cy.get(domSelectors.notification).should('contain', 'Delete successfully');
   });
-})
+});
diff --git a/web/cypress/integration/user/login.spec.js b/web/cypress/integration/user/login.spec.js
index 65e67c2..60adad7 100644
--- a/web/cypress/integration/user/login.spec.js
+++ b/web/cypress/integration/user/login.spec.js
@@ -19,7 +19,7 @@
 context('Login Test', () => {
   beforeEach(() => {
     // set default language
-    localStorage.setItem('umi_locale', "en-US");
+    localStorage.setItem('umi_locale', 'en-US');
   });
 
   it('login failed with empty username and password', () => {
@@ -44,4 +44,4 @@ context('Login Test', () => {
     cy.contains('Login').click();
     cy.get('.ant-notification-notice-message').should('contain', 'Successfully');
   });
-})
+});
diff --git a/web/cypress/integration/user/logout.spec.js b/web/cypress/integration/user/logout.spec.js
index 853f334..ec3f368 100644
--- a/web/cypress/integration/user/logout.spec.js
+++ b/web/cypress/integration/user/logout.spec.js
@@ -24,11 +24,11 @@ context('Logout Test', () => {
   it('logout', () => {
     cy.visit('/');
     cy.contains('.anticon', 'APISIX User', {
-      matchCase: false
+      matchCase: false,
     }).click({
-      force: true
+      force: true,
     });
     cy.get('[aria-label=logout]').click();
     cy.url().should('contains', '/user/login');
   });
-})
+});
diff --git a/web/cypress/plugins/index.js b/web/cypress/plugins/index.js
index ed129f2..1e51e89 100644
--- a/web/cypress/plugins/index.js
+++ b/web/cypress/plugins/index.js
@@ -21,4 +21,4 @@
 module.exports = (on, config) => {
   // `on` is used to hook into various events Cypress emits
   // `config` is the resolved Cypress config
-}
+};
diff --git a/web/cypress/support/commands.js b/web/cypress/support/commands.js
index bfb1955..5ff9062 100644
--- a/web/cypress/support/commands.js
+++ b/web/cypress/support/commands.js
@@ -22,20 +22,15 @@ Cypress.Commands.add('login', () => {
     test: 'http://localhost:9000',
   };
 
-  const {
-    SERVE_ENV = 'dev'
-  } = Cypress.env();
+  const { SERVE_ENV = 'dev' } = Cypress.env();
 
   cy.request('POST', `${serveUrlMap[SERVE_ENV]}/apisix/admin/user/login`, {
-      "username": "user",
-      "password": "user"
-    })
-    .then(res => {
-      expect(res.body.code).to.equal(0);
-      localStorage.setItem(
-        'token', res.body.data.token
-      );
-      // set default language
-      localStorage.setItem('umi_locale', "en-US");
-    })
-})
+    username: 'user',
+    password: 'user',
+  }).then((res) => {
+    expect(res.body.code).to.equal(0);
+    localStorage.setItem('token', res.body.data.token);
+    // set default language
+    localStorage.setItem('umi_locale', 'en-US');
+  });
+});
diff --git a/web/cypress/support/index.js b/web/cypress/support/index.js
index 113a8ce..a7c4744 100644
--- a/web/cypress/support/index.js
+++ b/web/cypress/support/index.js
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 /* eslint-disable no-undef */
-import './commands'
+import './commands';
 
 Cypress.on('uncaught:exception', () => {
   // returning false here prevents Cypress from
   // failing the test
-  return false
-})
+  return false;
+});
diff --git a/web/src/components/Plugin/PluginPage.tsx b/web/src/components/Plugin/PluginPage.tsx
index e9b10af..e88f417 100644
--- a/web/src/components/Plugin/PluginPage.tsx
+++ b/web/src/components/Plugin/PluginPage.tsx
@@ -49,7 +49,7 @@ const PluginPage: React.FC<Props> = ({
   readonly = false,
   initialData = {},
   schemaType = '',
-  onChange = () => { },
+  onChange = () => {},
 }) => {
   const [pluginList, setPlugin] = useState<PluginComponent.Meta[][]>([]);
   const [name, setName] = useState<string>(NEVER_EXIST_PLUGIN_FLAG);
@@ -95,9 +95,7 @@ const PluginPage: React.FC<Props> = ({
         let description = '';
         switch (err.keyword) {
           case 'enum':
-            description = `${err.dataPath} ${err.message}: ${err.params.allowedValues.join(
-              ', ',
-            )}`;
+            description = `${err.dataPath} ${err.message}: ${err.params.allowedValues.join(', ')}`;
             break;
           case 'minItems':
           case 'type':
diff --git a/web/src/components/RightContent/AvatarDropdown.tsx b/web/src/components/RightContent/AvatarDropdown.tsx
index 88c8c39..a87f831 100644
--- a/web/src/components/RightContent/AvatarDropdown.tsx
+++ b/web/src/components/RightContent/AvatarDropdown.tsx
@@ -24,7 +24,7 @@
 import React, { useCallback } from 'react';
 import { SettingOutlined, UserOutlined, SettingFilled, LogoutOutlined } from '@ant-design/icons';
 import { Avatar, Menu, Spin } from 'antd';
-import { history, useModel } from 'umi';
+import { history, useModel, useIntl } from 'umi';
 
 import { stringify } from 'querystring';
 import HeaderDropdown from '../HeaderDropdown';
@@ -47,6 +47,7 @@ const settings = async () => {
 };
 
 const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
+  const { formatMessage } = useIntl();
   const { initialState, setInitialState } = useModel('@@initialState');
 
   const onMenuClick = useCallback((event) => {
@@ -97,25 +98,25 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
       {menu && (
         <Menu.Item key="center">
           <UserOutlined />
-          个人中心
+          {formatMessage({ id: 'menu.account.center' })}
         </Menu.Item>
       )}
       {menu && (
         <Menu.Item key="settings">
           <SettingOutlined />
-          个人设置
+          {formatMessage({ id: 'menu.setting' })}
         </Menu.Item>
       )}
       {menu && <Menu.Divider />}
 
       <Menu.Item key="settings">
         <SettingFilled />
-        修改设置
+        {formatMessage({ id: 'menu.setting' })}
       </Menu.Item>
       <Menu.Divider />
       <Menu.Item key="logout">
         <LogoutOutlined />
-        退出
+        {formatMessage({ id: 'menu.account.logout' })}
       </Menu.Item>
     </Menu>
   );
diff --git a/web/src/components/Upstream/UpstreamForm.tsx b/web/src/components/Upstream/UpstreamForm.tsx
index cf88245..3e7cff7 100644
--- a/web/src/components/Upstream/UpstreamForm.tsx
+++ b/web/src/components/Upstream/UpstreamForm.tsx
@@ -63,21 +63,6 @@ type Props = {
   ref?: any;
 };
 
-const timeoutFields = [
-  {
-    label: '连接超时',
-    name: ['timeout', 'connect'],
-  },
-  {
-    label: '发送超时',
-    name: ['timeout', 'send'],
-  },
-  {
-    label: '接收超时',
-    name: ['timeout', 'read'],
-  },
-];
-
 const removeBtnStyle = {
   marginLeft: -10,
   display: 'flex',
@@ -91,6 +76,21 @@ const UpstreamForm: React.FC<Props> = forwardRef(
       Boolean(form.getFieldValue('upstream_id')) || disabled,
     );
 
+    const timeoutFields = [
+      {
+        label: formatMessage({ id: 'page.upstream.step.connect.timeout' }),
+        name: ['timeout', 'connect'],
+      },
+      {
+        label: formatMessage({ id: 'page.upstream.step.send.timeout' }),
+        name: ['timeout', 'send'],
+      },
+      {
+        label: formatMessage({ id: 'page.upstream.step.read.timeout' }),
+        name: ['timeout', 'read'],
+      },
+    ];
+
     useImperativeHandle(ref, () => ({
       getData: () => transformRequest(form.getFieldsValue()),
     }));
@@ -101,7 +101,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
         setReadonly(true);
         requestAnimationFrame(() => {
           form.setFieldsValue(list.find((item) => item.id === id));
-        })
+        });
       }
     }, [list]);
 
@@ -137,9 +137,13 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               <Form.Item
                 required
                 key={field.key}
-                label={index === 0 && '节点域名/IP'}
+                label={
+                  index === 0 &&
+                  formatMessage({ id: 'page.upstream.form.item-label.node.domain.or.ip' })
+                }
                 extra={
-                  index === 0 && '使用域名时,默认解析本地 /etc/resolv.conf;权重为0则熔断该节点'
+                  index === 0 &&
+                  formatMessage({ id: 'page.upstream.form.item.extra-message.node.domain.or.ip' })
                 }
                 labelCol={{ span: index === 0 ? 3 : 0 }}
                 wrapperCol={{ offset: index === 0 ? 0 : 3 }}
@@ -152,7 +156,9 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                       rules={[
                         {
                           required: true,
-                          message: formatMessage({ id: 'upstream.step.input.domain.name.or.ip' }),
+                          message: formatMessage({
+                            id: 'page.upstream.step.input.domain.name.or.ip',
+                          }),
                         },
                         {
                           pattern: new RegExp(
@@ -162,7 +168,10 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                         },
                       ]}
                     >
-                      <Input placeholder="域名/IP" disabled={readonly} />
+                      <Input
+                        placeholder={formatMessage({ id: 'page.upstream.step.domain.name.or.ip' })}
+                        disabled={readonly}
+                      />
                     </Form.Item>
                   </Col>
                   <Col span={2}>
@@ -172,11 +181,16 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                       rules={[
                         {
                           required: true,
-                          message: formatMessage({ id: 'upstream.step.input.port' }),
+                          message: formatMessage({ id: 'page.upstream.step.input.port' }),
                         },
                       ]}
                     >
-                      <InputNumber placeholder="端口号" disabled={readonly} min={1} max={65535} />
+                      <InputNumber
+                        placeholder={formatMessage({ id: 'page.upstream.step.port' })}
+                        disabled={readonly}
+                        min={1}
+                        max={65535}
+                      />
                     </Form.Item>
                   </Col>
                   <Col span={2}>
@@ -186,11 +200,16 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                       rules={[
                         {
                           required: true,
-                          message: formatMessage({ id: 'upstream.step.input.weight' }),
+                          message: formatMessage({ id: 'page.upstream.step.input.weight' }),
                         },
                       ]}
                     >
-                      <InputNumber placeholder="权重" disabled={readonly} min={0} max={1000} />
+                      <InputNumber
+                        placeholder={formatMessage({ id: 'page.upstream.step.weight' })}
+                        disabled={readonly}
+                        min={0}
+                        max={1000}
+                      />
                     </Form.Item>
                   </Col>
                   <Col style={removeBtnStyle}>
@@ -205,7 +224,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               <Form.Item wrapperCol={{ offset: 3 }}>
                 <Button type="dashed" onClick={add}>
                   <PlusOutlined />
-                  创建节点
+                  {formatMessage({ id: 'page.upstream.step.create.node' })}
                 </Button>
               </Form.Item>
             )}
@@ -216,14 +235,14 @@ const UpstreamForm: React.FC<Props> = forwardRef(
 
     const ActiveHealthCheck = () => (
       <>
-        <Form.Item label="超时时间">
+        <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.timeout' })}>
           <Form.Item name={['checks', 'active', 'timeout']} noStyle>
             <InputNumber disabled={readonly} />
           </Form.Item>
           <span style={{ margin: '0 8px' }}>s</span>
         </Form.Item>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.active.host' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeHost' })}
           required
         >
           <Form.Item
@@ -232,35 +251,39 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             rules={[
               {
                 required: true,
-                message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' }),
+                message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.activeHost' }),
               },
               {
                 pattern: new RegExp(
                   /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/,
                   'g',
                 ),
-                message: formatMessage({ id: 'upstream.step.domain.name.or.ip.rule' }),
+                message: formatMessage({ id: 'page.upstream.step.domain.name.or.ip.rule' }),
               },
             ]}
           >
             <Input
-              placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' })}
+              placeholder={formatMessage({
+                id: 'page.upstream.step.input.healthyCheck.activeHost',
+              })}
               disabled={readonly}
             />
           </Form.Item>
         </Form.Item>
 
-        <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.active.port' })}>
+        <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.activePort' })}>
           <Form.Item name={['checks', 'active', 'port']} noStyle>
             <InputNumber
-              placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.port' })}
+              placeholder={formatMessage({
+                id: 'page.upstream.step.input.healthyCheck.activePort',
+              })}
               disabled={readonly}
             />
           </Form.Item>
         </Form.Item>
 
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.active.http_path' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.http_path' })}
           required
         >
           <Form.Item
@@ -270,7 +293,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               {
                 required: true,
                 message: formatMessage({
-                  id: 'upstream.step.input.healthy.checks.active.http_path',
+                  id: 'page.upstream.step.input.healthyCheck.active.http_path',
                 }),
               },
             ]}
@@ -278,17 +301,17 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             <Input
               disabled={readonly}
               placeholder={formatMessage({
-                id: 'upstream.step.input.healthy.checks.active.http_path',
+                id: 'page.upstream.step.input.healthyCheck.active.http_path',
               })}
             />
           </Form.Item>
         </Form.Item>
 
         <Divider orientation="left" plain>
-          健康状态
+          {formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })}
         </Divider>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
           required
         >
           <Form.Item
@@ -298,7 +321,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               {
                 required: true,
                 message: formatMessage({
-                  id: 'upstream.step.input.healthy.checks.active.interval',
+                  id: 'page.upstream.step.input.healthyCheck.activeInterval',
                 }),
               },
             ]}
@@ -306,14 +329,17 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             <InputNumber disabled={readonly} min={1} />
           </Form.Item>
         </Form.Item>
-        <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
+        <Form.Item
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
+          required
+        >
           <Form.Item
             name={['checks', 'active', 'healthy', 'successes']}
             noStyle
             rules={[
               {
                 required: true,
-                message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }),
+                message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
               },
             ]}
           >
@@ -322,10 +348,10 @@ const UpstreamForm: React.FC<Props> = forwardRef(
         </Form.Item>
 
         <Divider orientation="left" plain>
-          不健康状态
+          {formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })}
         </Divider>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
           required
         >
           <Form.Item
@@ -335,7 +361,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               {
                 required: true,
                 message: formatMessage({
-                  id: 'upstream.step.input.healthy.checks.active.interval',
+                  id: 'page.upstream.step.input.healthyCheck.activeInterval',
                 }),
               },
             ]}
@@ -344,7 +370,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
           </Form.Item>
         </Form.Item>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
           required
         >
           <Form.Item
@@ -353,7 +379,9 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             rules={[
               {
                 required: true,
-                message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
+                message: formatMessage({
+                  id: 'page.upstream.step.input.healthyCheck.http_failures',
+                }),
               },
             ]}
           >
@@ -368,7 +396,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                   key={field.key}
                   label={
                     index === 0 &&
-                    formatMessage({ id: 'upstream.step.healthy.checks.active.req_headers' })
+                    formatMessage({ id: 'page.upstream.step.healthyCheck.active.req_headers' })
                   }
                   wrapperCol={{ offset: index === 0 ? 0 : 3 }}
                 >
@@ -377,7 +405,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                       <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
                         <Input
                           placeholder={formatMessage({
-                            id: 'upstream.step.input.healthy.checks.active.req_headers',
+                            id: 'page.upstream.step.input.healthyCheck.active.req_headers',
                           })}
                           disabled={readonly}
                         />
@@ -400,7 +428,9 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                 <Form.Item wrapperCol={{ offset: 3 }}>
                   <Button type="dashed" onClick={() => add()}>
                     <PlusOutlined />
-                    创建请求头
+                    {formatMessage({
+                      id: 'page.upstream.step.healthyCheck.active.create.req_headers',
+                    })}
                   </Button>
                 </Form.Item>
               )}
@@ -412,7 +442,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
     const InActiveHealthCheck = () => (
       <>
         <Divider orientation="left" plain>
-          健康状态
+          {formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })}
         </Divider>
         <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}>
           {(fields, { add, remove }) => (
@@ -423,7 +453,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                   key={field.key}
                   label={
                     index === 0 &&
-                    formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
+                    formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })
                   }
                   labelCol={{ span: index === 0 ? 3 : 0 }}
                   wrapperCol={{ offset: index === 0 ? 0 : 3 }}
@@ -450,21 +480,26 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                 <Form.Item wrapperCol={{ offset: 3 }}>
                   <Button type="dashed" onClick={() => add()}>
                     <PlusOutlined />
-                    创建状态码
+                    {formatMessage({
+                      id: 'page.upstream.step.healthyCheck.passive.create.http_statuses',
+                    })}
                   </Button>
                 </Form.Item>
               )}
             </>
           )}
         </Form.List>
-        <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
+        <Form.Item
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
+          required
+        >
           <Form.Item
             name={['checks', 'passive', 'healthy', 'successes']}
             noStyle
             rules={[
               {
                 required: true,
-                message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }),
+                message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
               },
             ]}
           >
@@ -473,7 +508,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
         </Form.Item>
 
         <Divider orientation="left" plain>
-          不健康状态
+          {formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })}
         </Divider>
         <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}>
           {(fields, { add, remove }) => (
@@ -484,7 +519,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                   key={field.key}
                   label={
                     index === 0 &&
-                    formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
+                    formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })
                   }
                   labelCol={{ span: index === 0 ? 3 : 0 }}
                   wrapperCol={{ offset: index === 0 ? 0 : 3 }}
@@ -511,7 +546,9 @@ const UpstreamForm: React.FC<Props> = forwardRef(
                 <Form.Item wrapperCol={{ offset: 3 }}>
                   <Button type="dashed" onClick={() => add()}>
                     <PlusOutlined />
-                    创建状态码
+                    {formatMessage({
+                      id: 'page.upstream.step.healthyCheck.passive.create.http_statuses',
+                    })}
                   </Button>
                 </Form.Item>
               )}
@@ -519,7 +556,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
           )}
         </Form.List>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
           required
         >
           <Form.Item
@@ -528,7 +565,9 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             rules={[
               {
                 required: true,
-                message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
+                message: formatMessage({
+                  id: 'page.upstream.step.input.healthyCheck.http_failures',
+                }),
               },
             ]}
           >
@@ -536,7 +575,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
           </Form.Item>
         </Form.Item>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.healthy.checks.passive.tcp_failures' })}
+          label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.tcp_failures' })}
           required
         >
           <Form.Item
@@ -546,7 +585,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               {
                 required: true,
                 message: formatMessage({
-                  id: 'upstream.step.input.healthy.checks.passive.tcp_failures',
+                  id: 'page.upstream.step.input.healthyCheck.passive.tcp_failures',
                 }),
               },
             ]}
@@ -566,26 +605,36 @@ const UpstreamForm: React.FC<Props> = forwardRef(
         }}
       >
         {showSelector && (
-          <Form.Item label="选择上游" name="upstream_id" shouldUpdate={(prev, next) => {
-            setReadonly(Boolean(next.upstream_id));
-            if (prev.upstream_id !== next.upstream_id) {
-              const id = next.upstream_id;
-              if (id) {
-                form.setFieldsValue(list.find((item) => item.id === id));
-                form.setFieldsValue({
-                  upstream_id: id,
-                });
+          <Form.Item
+            label={formatMessage({ id: 'page.upstream.step.select.upstream' })}
+            name="upstream_id"
+            shouldUpdate={(prev, next) => {
+              setReadonly(Boolean(next.upstream_id));
+              if (prev.upstream_id !== next.upstream_id) {
+                const id = next.upstream_id;
+                if (id) {
+                  form.setFieldsValue(list.find((item) => item.id === id));
+                  form.setFieldsValue({
+                    upstream_id: id,
+                  });
+                }
               }
-            }
-            return prev.upstream_id !== next.upstream_id;
-          }}>
+              return prev.upstream_id !== next.upstream_id;
+            }}
+          >
             <Select
               disabled={disabled}
               onChange={(id) => {
                 form.setFieldsValue(list.find((item) => item.id === id));
               }}
             >
-              {[{ name: '手动填写', id: '' }, ...list].map((item) => (
+              {[
+                {
+                  name: formatMessage({ id: 'page.upstream.step.select.upstream.select.option' }),
+                  id: '',
+                },
+                ...list,
+              ].map((item) => (
                 <Select.Option value={item.id!} key={item.id}>
                   {item.name}
                 </Select.Option>
@@ -594,7 +643,11 @@ const UpstreamForm: React.FC<Props> = forwardRef(
           </Form.Item>
         )}
 
-        <Form.Item label="类型" name="type" rules={[{ required: true }]}>
+        <Form.Item
+          label={formatMessage({ id: 'page.upstream.step.type' })}
+          name="type"
+          rules={[{ required: true }]}
+        >
           <Select disabled={readonly}>
             {Object.entries(Type).map(([label, value]) => {
               return (
@@ -615,19 +668,19 @@ const UpstreamForm: React.FC<Props> = forwardRef(
         </Form.Item>
         {NodeList()}
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.pass-host' })}
+          label={formatMessage({ id: 'page.upstream.step.pass-host' })}
           name="pass_host"
-          extra={formatMessage({ id: 'upstream.step.pass-host.tips' })}
+          extra={formatMessage({ id: 'page.upstream.step.pass-host.tips' })}
         >
           <Select disabled={readonly}>
             <Select.Option value="pass">
-              {formatMessage({ id: 'upstream.step.pass-host.pass' })}
+              {formatMessage({ id: 'page.upstream.step.pass-host.pass' })}
             </Select.Option>
             <Select.Option value="node">
-              {formatMessage({ id: 'upstream.step.pass-host.node' })}
+              {formatMessage({ id: 'page.upstream.step.pass-host.node' })}
             </Select.Option>
             <Select.Option value="rewrite">
-              {formatMessage({ id: 'upstream.step.pass-host.rewrite' })}
+              {formatMessage({ id: 'page.upstream.step.pass-host.rewrite' })}
             </Select.Option>
           </Select>
         </Form.Item>
@@ -641,7 +694,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
             if (form.getFieldValue('pass_host') === 'rewrite') {
               return (
                 <Form.Item
-                  label={formatMessage({ id: 'upstream.step.pass-host.upstream_host' })}
+                  label={formatMessage({ id: 'page.upstream.step.pass-host.upstream_host' })}
                   name="upstream_host"
                 >
                   <Input disabled={readonly} />
@@ -660,7 +713,7 @@ const UpstreamForm: React.FC<Props> = forwardRef(
               rules={[
                 {
                   required: true,
-                  message: formatMessage({ id: `upstream.step.input.${name[1]}.timeout` }),
+                  message: formatMessage({ id: `page.upstream.step.input.${name[1]}.timeout` }),
                 },
               ]}
             >
@@ -670,15 +723,17 @@ const UpstreamForm: React.FC<Props> = forwardRef(
           </Form.Item>
         ))}
 
-        <PanelSection title="健康检查">
+        <PanelSection
+          title={formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.check' })}
+        >
           {[
             {
-              label: '探活健康检查',
+              label: formatMessage({ id: 'page.upstream.step.healthyCheck.active' }),
               name: ['checks', 'active'],
               component: <ActiveHealthCheck />,
             },
             {
-              label: '被动健康检查',
+              label: formatMessage({ id: 'page.upstream.step.healthyCheck.passive' }),
               name: ['checks', 'passive'],
               component: <InActiveHealthCheck />,
             },
diff --git a/web/src/helpers.tsx b/web/src/helpers.tsx
index ac40f42..2942aee 100644
--- a/web/src/helpers.tsx
+++ b/web/src/helpers.tsx
@@ -32,16 +32,16 @@ export const getMenuData = (): MenuDataItem[] => {
       icon: <IconFont name="icondashboard" />,
     },
     {
+      name: 'service',
+      path: '/service/list',
+      icon: <IconFont name="iconconsumer" />,
+    },
+    {
       name: 'routes',
       path: '/routes/list',
       icon: <IconFont name="iconroute" />,
     },
     {
-      name: 'ssl',
-      path: '/ssl/list',
-      icon: <IconFont name="iconssl" />,
-    },
-    {
       name: 'upstream',
       path: '/upstream/list',
       icon: <IconFont name="iconserver" />,
@@ -52,9 +52,9 @@ export const getMenuData = (): MenuDataItem[] => {
       icon: <IconFont name="iconconsumer" />,
     },
     {
-      name: 'service',
-      path: '/service/list',
-      icon: <IconFont name="iconconsumer" />,
+      name: 'ssl',
+      path: '/ssl/list',
+      icon: <IconFont name="iconssl" />,
     },
     {
       name: 'setting',
diff --git a/web/src/locales/en-US/component.ts b/web/src/locales/en-US/component.ts
index a712701..946a735 100644
--- a/web/src/locales/en-US/component.ts
+++ b/web/src/locales/en-US/component.ts
@@ -18,6 +18,8 @@ export default {
   'component.tagSelect.expand': 'Expand',
   'component.tagSelect.collapse': 'Collapse',
   'component.tagSelect.all': 'All',
+  'component.global.search': 'Search',
+  'component.global.reset': 'Reset',
   'component.global.confirm': 'Confirm',
   'component.global.delete': 'Delete',
   'component.global.cancel': 'Cancel',
diff --git a/web/src/locales/en-US/menu.ts b/web/src/locales/en-US/menu.ts
index 325d1cd..ae4018a 100644
--- a/web/src/locales/en-US/menu.ts
+++ b/web/src/locales/en-US/menu.ts
@@ -57,7 +57,6 @@ export default {
   'menu.exception.trigger': 'Trigger',
   'menu.account': 'Account',
   'menu.account.center': 'Account Center',
-  'menu.account.settings': 'Account Settings',
   'menu.account.trigger': 'Trigger Error',
   'menu.account.logout': 'Logout',
   'menu.editor': 'Graphic Editor',
diff --git a/web/src/locales/zh-CN/component.ts b/web/src/locales/zh-CN/component.ts
index b62ba40..d0829c6 100644
--- a/web/src/locales/zh-CN/component.ts
+++ b/web/src/locales/zh-CN/component.ts
@@ -18,6 +18,8 @@ export default {
   'component.tagSelect.expand': '展开',
   'component.tagSelect.collapse': '收起',
   'component.tagSelect.all': '全部',
+  'component.global.search': '查询',
+  'component.global.reset': '重置',
   'component.global.confirm': '确认',
   'component.global.delete': '删除',
   'component.global.cancel': '取消',
diff --git a/web/src/locales/zh-CN/menu.ts b/web/src/locales/zh-CN/menu.ts
index aef67b3..6524131 100644
--- a/web/src/locales/zh-CN/menu.ts
+++ b/web/src/locales/zh-CN/menu.ts
@@ -57,7 +57,6 @@ export default {
   'menu.exception.trigger': '触发错误',
   'menu.account': '个人页',
   'menu.account.center': '个人中心',
-  'menu.account.settings': '个人设置',
   'menu.account.trigger': '触发报错',
   'menu.account.logout': '退出登录',
   'menu.editor': '图形编辑器',
diff --git a/web/src/pages/Consumer/List.tsx b/web/src/pages/Consumer/List.tsx
index 78d1587..08f3dd6 100644
--- a/web/src/pages/Consumer/List.tsx
+++ b/web/src/pages/Consumer/List.tsx
@@ -93,6 +93,10 @@ const Page: React.FC = () => {
         columns={columns}
         rowKey="id"
         request={fetchList}
+        search={{
+          searchText: formatMessage({ id: 'component.global.search' }),
+          resetText: formatMessage({ id: 'component.global.reset' }),
+        }}
         toolBarRender={() => [
           <Button type="primary" onClick={() => history.push(`/consumer/create`)}>
             <PlusOutlined />
diff --git a/web/src/pages/Route/Create.tsx b/web/src/pages/Route/Create.tsx
index 4fcc921..41cadae 100644
--- a/web/src/pages/Route/Create.tsx
+++ b/web/src/pages/Route/Create.tsx
@@ -113,7 +113,7 @@ const Page: React.FC<Props> = (props) => {
               setAdvancedMatchingRules(data);
             }
             if (action === 'labelsChange') {
-              form1.setFieldsValue({ ...form1.getFieldsValue(), labels: data })
+              form1.setFieldsValue({ ...form1.getFieldsValue(), labels: data });
             }
           }}
           isEdit={props.route.path.indexOf('edit') > 0}
@@ -256,10 +256,11 @@ const Page: React.FC<Props> = (props) => {
   return (
     <>
       <PageHeaderWrapper
-        title={`${(props as any).match.params.rid
-          ? formatMessage({ id: 'component.global.edit' })
-          : formatMessage({ id: 'component.global.create' })
-          } ${formatMessage({ id: 'menu.routes' })}`}
+        title={`${
+          (props as any).match.params.rid
+            ? formatMessage({ id: 'component.global.edit' })
+            : formatMessage({ id: 'component.global.create' })
+        } ${formatMessage({ id: 'menu.routes' })}`}
       >
         <Card bordered={false}>
           <Steps current={step - 1} className={styles.steps}>
diff --git a/web/src/pages/Route/List.tsx b/web/src/pages/Route/List.tsx
index c131899..304ad3b 100644
--- a/web/src/pages/Route/List.tsx
+++ b/web/src/pages/Route/List.tsx
@@ -25,7 +25,6 @@ import { timestampToLocaleString } from '@/helpers';
 import { fetchList, remove, fetchLabelList, updateRouteStatus } from './service';
 import { DebugDrawView } from './components/DebugViews';
 
-
 const { OptGroup, Option } = Select;
 
 const Page: React.FC = () => {
@@ -52,14 +51,16 @@ const Page: React.FC = () => {
 
   const handlePublishOffline = (rid: string, status: RouteModule.RouteStatus) => {
     updateRouteStatus(rid, status).then(() => {
-      const actionName = status ? formatMessage({ id: 'page.route.publish' }) : formatMessage({ id: 'page.route.offline' })
+      const actionName = status
+        ? formatMessage({ id: 'page.route.publish' })
+        : formatMessage({ id: 'page.route.offline' });
       handleTableActionSuccessResponse(
         `${actionName} ${formatMessage({
           id: 'menu.routes',
         })} ${formatMessage({ id: 'component.status.success' })}`,
       );
     });
-  }
+  };
 
   const [debugDrawVisible, setDebugDrawVisible] = useState(false);
 
@@ -130,14 +131,17 @@ const Page: React.FC = () => {
               return (
                 <OptGroup label={key} key={Math.random().toString(36).slice(2)}>
                   {(labelList[key] || []).map((value: string) => (
-                    <Option key={Math.random().toString(36).slice(2)} value={`${key}:${value}`}> {value} </Option>
+                    <Option key={Math.random().toString(36).slice(2)} value={`${key}:${value}`}>
+                      {' '}
+                      {value}{' '}
+                    </Option>
                   ))}
                 </OptGroup>
               );
             })}
           </Select>
         );
-      }
+      },
     },
     {
       title: formatMessage({ id: 'page.route.status' }),
@@ -147,8 +151,8 @@ const Page: React.FC = () => {
           {record.status ? (
             <Tag color="green">{formatMessage({ id: 'page.route.published' })}</Tag>
           ) : (
-              <Tag color="red">{formatMessage({ id: 'page.route.unpublished' })}</Tag>
-            )}
+            <Tag color="red">{formatMessage({ id: 'page.route.unpublished' })}</Tag>
+          )}
         </>
       ),
     },
@@ -175,7 +179,7 @@ const Page: React.FC = () => {
             <Button
               type="primary"
               onClick={() => {
-                handlePublishOffline(record.id, RouteStatus.Publish)
+                handlePublishOffline(record.id, RouteStatus.Publish);
               }}
               style={{ marginRight: 10 }}
               disabled={Boolean(record.status)}
@@ -185,7 +189,7 @@ const Page: React.FC = () => {
             <Popconfirm
               title={formatMessage({ id: 'page.route.popconfirm.title.offline' })}
               onConfirm={() => {
-                handlePublishOffline(record.id, RouteStatus.Offline)
+                handlePublishOffline(record.id, RouteStatus.Offline);
               }}
               okText={formatMessage({ id: 'component.global.confirm' })}
               cancelText={formatMessage({ id: 'component.global.cancel' })}
@@ -230,6 +234,10 @@ const Page: React.FC = () => {
         rowKey="id"
         columns={columns}
         request={fetchList}
+        search={{
+          searchText: formatMessage({ id: 'component.global.search' }),
+          resetText: formatMessage({ id: 'component.global.reset' }),
+        }}
         toolBarRender={() => [
           <Button type="primary" onClick={() => history.push(`/routes/create`)}>
             <PlusOutlined />
diff --git a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
index 16c15db..c73af82 100644
--- a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
+++ b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
@@ -39,7 +39,7 @@ const { TabPane } = Tabs;
 const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => {
   const { formatMessage } = useIntl();
   const [httpMethod, setHttpMethod] = useState(HTTP_METHOD_OPTION_LIST[0]);
-  const [requestProtocol, setRequestProtocol] = useState(PROTOCOL_SUPPORTED[0])
+  const [requestProtocol, setRequestProtocol] = useState(PROTOCOL_SUPPORTED[0]);
   const [showBodyTab, setShowBodyTab] = useState(false);
   const [queryForm] = Form.useForm();
   const [bodyForm] = Form.useForm();
diff --git a/web/src/pages/Route/components/Step1/LabelsDrawer.tsx b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx
index 6fb0a70..ba5b221 100644
--- a/web/src/pages/Route/components/Step1/LabelsDrawer.tsx
+++ b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx
@@ -111,7 +111,7 @@ const LabelsDrawer: React.FC<Props> = ({
   disabled,
   labelsDataSource,
   onClose,
-  onChange = () => { },
+  onChange = () => {},
 }) => {
   const transformLabel = transformLableValueToKeyValue(labelsDataSource);
 
@@ -141,7 +141,7 @@ const LabelsDrawer: React.FC<Props> = ({
             onClick={(e) => {
               e.persist();
               form.validateFields().then(({ labels }) => {
-                const data = labels.map((item: any) => `${item.labelKey}:${item.labelValue}`)
+                const data = labels.map((item: any) => `${item.labelKey}:${item.labelValue}`);
                 // check for duplicates
                 if (new Set(data).size !== data.length) {
                   notification.warning({
@@ -161,13 +161,13 @@ const LabelsDrawer: React.FC<Props> = ({
           >
             {formatMessage({ id: 'component.global.confirm' })}
           </Button>
-        </div >
+        </div>
       }
     >
       <Form form={form} layout="horizontal">
         {LabelList(disabled, labelList || {})}
       </Form>
-    </Drawer >
+    </Drawer>
   );
 };
 
diff --git a/web/src/pages/Route/components/Step1/MetaView.tsx b/web/src/pages/Route/components/Step1/MetaView.tsx
index 8234be9..25e1f31 100644
--- a/web/src/pages/Route/components/Step1/MetaView.tsx
+++ b/web/src/pages/Route/components/Step1/MetaView.tsx
@@ -23,7 +23,7 @@ import { PanelSection } from '@api7-dashboard/ui';
 import { FORM_ITEM_WITHOUT_LABEL } from '@/pages/Route/constants';
 import LabelsDrawer from './LabelsDrawer';
 
-const MetaView: React.FC<RouteModule.Step1PassProps> = ({ disabled, form, isEdit, onChange, }) => {
+const MetaView: React.FC<RouteModule.Step1PassProps> = ({ disabled, form, isEdit, onChange }) => {
   const { formatMessage } = useIntl();
   const [visible, setVisible] = useState(false);
 
diff --git a/web/src/pages/Route/components/Step1/RequestConfigView.tsx b/web/src/pages/Route/components/Step1/RequestConfigView.tsx
index 957d260..7ad1631 100644
--- a/web/src/pages/Route/components/Step1/RequestConfigView.tsx
+++ b/web/src/pages/Route/components/Step1/RequestConfigView.tsx
@@ -31,7 +31,7 @@ import { fetchServiceList } from '../../service';
 const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
   form,
   disabled,
-  onChange = () => { },
+  onChange = () => {},
 }) => {
   const { formatMessage } = useIntl();
   const [serviceList, setServiceList] = useState<ServiceModule.ResponseBody[]>([]);
@@ -383,17 +383,18 @@ const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
           return null;
         }}
       </Form.Item>
-      <Form.Item
-        label={formatMessage({ id: 'page.route.service' })}
-        name='service_id'
-      >
+      <Form.Item label={formatMessage({ id: 'page.route.service' })} name="service_id">
         <Select disabled={disabled}>
           {/* TODO: value === '' means  no service_id select, need to find a better way */}
-          <Select.Option value='' key={Math.random().toString(36).substring(7)}>None</Select.Option>
-          {serviceList.map(item => {
-            return <Select.Option value={item.id} key={item.id}>
-              {item.name}
-            </Select.Option>
+          <Select.Option value="" key={Math.random().toString(36).substring(7)}>
+            None
+          </Select.Option>
+          {serviceList.map((item) => {
+            return (
+              <Select.Option value={item.id} key={item.id}>
+                {item.name}
+              </Select.Option>
+            );
           })}
         </Select>
       </Form.Item>
diff --git a/web/src/pages/Route/constants.ts b/web/src/pages/Route/constants.ts
index ab6c30c..1a8dc46 100644
--- a/web/src/pages/Route/constants.ts
+++ b/web/src/pages/Route/constants.ts
@@ -43,7 +43,7 @@ export const FORM_ITEM_WITHOUT_LABEL = {
 export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = {
   name: '',
   desc: '',
-  labels:[],
+  labels: [],
   status: 1,
   priority: 0,
   websocket: false,
@@ -54,6 +54,7 @@ export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = {
   redirectURI: '',
   ret_code: 302,
   methods: HTTP_METHOD_OPTION_LIST,
+  service_id: '',
 };
 
 export const DEFAULT_STEP_3_DATA: RouteModule.Step3Data = {
@@ -87,7 +88,7 @@ export const HASH_ON_LIST = ['vars', 'header', 'cookie', 'consumer'];
 
 export const AUTH_LIST = ['basic-auth', 'jwt-auth', 'key-auth'];
 
-export const PROTOCOL_SUPPORTED = ['http', 'https'];
+export const PROTOCOL_SUPPORTED: RouteModule.debugRequest['request_protocol'][] = ['http', 'https'];
 
 export const DEFAULT_DEBUG_PARAM_FORM_DATA = {
   params: [
diff --git a/web/src/pages/Route/service.ts b/web/src/pages/Route/service.ts
index 099428b..bc1a469 100644
--- a/web/src/pages/Route/service.ts
+++ b/web/src/pages/Route/service.ts
@@ -21,7 +21,7 @@ import {
   transformStepData,
   transformRouteData,
   transformUpstreamNodes,
-  transformLabelList
+  transformLabelList,
 } from './transform';
 
 export const create = (data: RouteModule.RequestData) =>
@@ -37,7 +37,7 @@ export const update = (rid: number, data: RouteModule.RequestData) =>
   });
 
 export const fetchItem = (rid: number) =>
-  request(`/routes/${rid}`).then((data) => (transformRouteData(data.data)));
+  request(`/routes/${rid}`).then((data) => transformRouteData(data.data));
 
 export const fetchList = ({ current = 1, pageSize = 10, ...res }) => {
   const { labels } = res;
@@ -94,12 +94,14 @@ export const checkHostWithSSL = (hosts: string[]) =>
   });
 
 export const fetchLabelList = () =>
-  request('/labels/route').then(({ data }) => ((transformLabelList(data.rows)) as RouteModule.LabelList));
+  request('/labels/route').then(
+    ({ data }) => transformLabelList(data.rows) as RouteModule.LabelList,
+  );
 
 export const updateRouteStatus = (rid: string, status: RouteModule.RouteStatus) =>
   request(`/routes/${rid}`, {
     method: 'PATCH',
-    data: { status }
+    data: { status },
   });
 
 export const debugRoute = (data: RouteModule.debugRequest) => {
diff --git a/web/src/pages/Route/transform.ts b/web/src/pages/Route/transform.ts
index c7b442d..401b15d 100644
--- a/web/src/pages/Route/transform.ts
+++ b/web/src/pages/Route/transform.ts
@@ -45,9 +45,9 @@ export const transformStepData = ({
   }
 
   const labels = {};
-  transformLableValueToKeyValue(form1Data.labels).forEach(item => {
+  transformLableValueToKeyValue(form1Data.labels).forEach((item) => {
     labels[item.labelKey] = item.labelValue;
-  })
+  });
   const { service_id = '' } = form1Data;
 
   const data: Partial<RouteModule.Body> = {
@@ -70,7 +70,7 @@ export const transformStepData = ({
       return [key, operator, value];
     }),
     // @ts-ignore
-    methods: form1Data.methods.includes("ALL") ? [] : form1Data.methods
+    methods: form1Data.methods.includes('ALL') ? [] : form1Data.methods,
   };
 
   if (Object.keys(redirect).length === 0 || redirect.http_to_https) {
@@ -171,7 +171,7 @@ export const transformRouteData = (data: RouteModule.Body) => {
     upstream_id,
     service_id = '',
     priority = 0,
-    enable_websocket
+    enable_websocket,
   } = data;
   const form1Data: Partial<RouteModule.Form1Data> = {
     name,
@@ -182,10 +182,10 @@ export const transformRouteData = (data: RouteModule.Body) => {
     remote_addrs: remote_addrs || [''],
     labels: Object.keys(labels || []).map((item) => `${item}:${labels[item]}`),
     // @ts-ignore
-    methods: methods.length ? methods : ["ALL"],
+    methods: methods.length ? methods : ['ALL'],
     priority,
     enable_websocket,
-    service_id
+    service_id,
   };
 
   const redirect = data.plugins?.redirect || {};
diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts
index f104b19..6b87a0b 100644
--- a/web/src/pages/Route/typing.d.ts
+++ b/web/src/pages/Route/typing.d.ts
@@ -124,10 +124,10 @@ declare namespace RouteModule {
   type LabelList = Record<string, string[]>;
 
   type LabelTableProps = {
-    labelKey: string,
-    labelValue: string,
-    key: string
-  }
+    labelKey: string;
+    labelValue: string;
+    key: string;
+  };
 
   type Step1PassProps = {
     form: FormInstance;
@@ -253,7 +253,7 @@ declare namespace RouteModule {
   // TODO: grpc and websocket
   type debugRequest = {
     url: string;
-    request_protocol: 'http' | 'grpc' | 'websocket';
+    request_protocol: 'http' | 'https' | 'grpc' | 'websocket';
     method: string;
     body_params?: any;
     header_params?: any;
diff --git a/web/src/pages/SSL/List.tsx b/web/src/pages/SSL/List.tsx
index bf607ea..c9a7dd5 100644
--- a/web/src/pages/SSL/List.tsx
+++ b/web/src/pages/SSL/List.tsx
@@ -106,6 +106,10 @@ const Page: React.FC = () => {
         columns={columns}
         actionRef={tableRef}
         request={fetchList}
+        search={{
+          searchText: formatMessage({ id: 'component.global.search' }),
+          resetText: formatMessage({ id: 'component.global.reset' }),
+        }}
         toolBarRender={() => [
           <Button type="primary" onClick={() => history.push(`/ssl/create`)}>
             <PlusOutlined />
diff --git a/web/src/pages/ServerInfo/List.tsx b/web/src/pages/ServerInfo/List.tsx
index 2f59050..c4ae9ad 100644
--- a/web/src/pages/ServerInfo/List.tsx
+++ b/web/src/pages/ServerInfo/List.tsx
@@ -54,7 +54,7 @@ const ServerInfo: React.FC = () => {
                 setData(
                   nodeList.find((item) => {
                     return item.id === value;
-                  })
+                  }),
                 );
               }}
             >
diff --git a/web/src/pages/ServerInfo/service.ts b/web/src/pages/ServerInfo/service.ts
index 0dc2029..60fab5b 100644
--- a/web/src/pages/ServerInfo/service.ts
+++ b/web/src/pages/ServerInfo/service.ts
@@ -17,7 +17,7 @@
 import { request } from 'umi';
 
 export const fetchInfoList = () => {
-  return request<Res<ResListData<ServerInfoModule.Node>>>(
-    '/server_info',
-  ).then(({ data }) => data.rows);
+  return request<Res<ResListData<ServerInfoModule.Node>>>('/server_info').then(
+    ({ data }) => data.rows,
+  );
 };
diff --git a/web/src/pages/Service/Create.tsx b/web/src/pages/Service/Create.tsx
index 3c8bf3a..5a644f5 100644
--- a/web/src/pages/Service/Create.tsx
+++ b/web/src/pages/Service/Create.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, { useState, useRef, useEffect } from 'react'
+import React, { useState, useRef, useEffect } from 'react';
 import { useIntl, history } from 'umi';
 import { Card, Steps, Form, notification } from 'antd';
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
@@ -24,7 +24,7 @@ import ActionBar from '@/components/ActionBar';
 import PluginPage from '@/components/Plugin';
 import { DEFAULT_UPSTREAM } from '@/components/Upstream';
 import Preview from './components/Preview';
-import Step1 from "./components/Step1";
+import Step1 from './components/Step1';
 import { create, update, fetchItem } from './service';
 
 const { Step } = Steps;
@@ -40,13 +40,12 @@ const Page: React.FC = (props) => {
     formatMessage({ id: 'page.service.steps.stepTitle.basicInformation' }),
     formatMessage({ id: 'page.service.steps.stepTitle.pluginConfig' }),
     formatMessage({ id: 'component.global.steps.stepTitle.preview' }),
-  ]
+  ];
 
   const [stepHeader] = useState(STEP_HEADER);
   const [step, setStep] = useState(1);
 
   useEffect(() => {
-
     // init upstream default value
     upstreamForm.setFieldsValue(DEFAULT_UPSTREAM);
 
@@ -82,12 +81,13 @@ const Page: React.FC = (props) => {
     (serviceId ? update(serviceId, data) : create(data))
       .then(() => {
         notification.success({
-          message: `${serviceId
-            ? formatMessage({ id: 'component.global.edit' })
-            : formatMessage({ id: 'component.global.create' })
-            } ${formatMessage({ id: 'menu.service' })} ${formatMessage({
-              id: 'component.status.success',
-            })}`,
+          message: `${
+            serviceId
+              ? formatMessage({ id: 'component.global.edit' })
+              : formatMessage({ id: 'component.global.create' })
+          } ${formatMessage({ id: 'menu.service' })} ${formatMessage({
+            id: 'component.status.success',
+          })}`,
         });
         history.push('/service/list');
       })
@@ -101,43 +101,44 @@ const Page: React.FC = (props) => {
       form.validateFields().then(() => {
         upstreamForm.validateFields().then(() => {
           setStep(nextStep);
-        })
-      })
+        });
+      });
       return;
     }
     if (nextStep === 4) {
       onSubmit();
       return;
-    };
+    }
     setStep(nextStep);
-  }
+  };
 
-  return (<>
-    <PageHeaderWrapper
-      title={`${(props as any).match.params.rid
-        ? formatMessage({ id: 'component.global.edit' })
-        : formatMessage({ id: 'component.global.create' })
+  return (
+    <>
+      <PageHeaderWrapper
+        title={`${
+          (props as any).match.params.rid
+            ? formatMessage({ id: 'component.global.edit' })
+            : formatMessage({ id: 'component.global.create' })
         } ${formatMessage({ id: 'menu.service' })}`}
-    >
-      <Card bordered={false}>
-        <Steps current={step - 1} style={{ marginBottom: "25px" }}>
-          {stepHeader.map((item) => (
-            <Step title={item} key={item} />
-          ))}
-        </Steps>
-        {step === 1 && <Step1
-          form={form}
-          upstreamForm={upstreamForm}
-          upstreamRef={upstreamRef}
-        />}
-        {step === 2 && (
-          <PluginPage initialData={plugins} onChange={setPlugins} schemaType="route" />
-        )}
-        {step === 3 && <Preview upstreamForm={upstreamForm} form={form} plugins={plugins} />}
-      </Card>
-    </PageHeaderWrapper>
-    <ActionBar step={step} lastStep={3} onChange={onStepChange} withResultView />
-  </>)
-}
+      >
+        <Card bordered={false}>
+          <Steps current={step - 1} style={{ marginBottom: '25px' }}>
+            {stepHeader.map((item) => (
+              <Step title={item} key={item} />
+            ))}
+          </Steps>
+          {step === 1 && (
+            <Step1 form={form} upstreamForm={upstreamForm} upstreamRef={upstreamRef} />
+          )}
+          {step === 2 && (
+            <PluginPage initialData={plugins} onChange={setPlugins} schemaType="route" />
+          )}
+          {step === 3 && <Preview upstreamForm={upstreamForm} form={form} plugins={plugins} />}
+        </Card>
+      </PageHeaderWrapper>
+      <ActionBar step={step} lastStep={3} onChange={onStepChange} withResultView />
+    </>
+  );
+};
 
 export default Page;
diff --git a/web/src/pages/Service/List.tsx b/web/src/pages/Service/List.tsx
index e3e5b99..c14d11c 100644
--- a/web/src/pages/Service/List.tsx
+++ b/web/src/pages/Service/List.tsx
@@ -31,7 +31,7 @@ const Page: React.FC = () => {
     {
       title: 'ID',
       dataIndex: 'id',
-      hideInSearch: true
+      hideInSearch: true,
     },
     {
       title: formatMessage({ id: 'component.global.name' }),
@@ -81,23 +81,26 @@ const Page: React.FC = () => {
     },
   ];
 
-  return (<PageHeaderWrapper
-    title={`${formatMessage({ id: 'menu.service' })} ${formatMessage({
-      id: 'component.global.list',
-    })}`}
-  >
-    <ProTable<ServiceModule.ResponseBody>
-      actionRef={ref}
-      rowKey="id"
-      columns={columns}
-      request={fetchList}
-      toolBarRender={() => [
-        <Button type="primary" onClick={() => history.push(`/service/create`)}>
-          <PlusOutlined />
-          {formatMessage({ id: 'component.global.create' })}
-        </Button>,
-      ]} />
-  </PageHeaderWrapper>)
-}
+  return (
+    <PageHeaderWrapper
+      title={`${formatMessage({ id: 'menu.service' })} ${formatMessage({
+        id: 'component.global.list',
+      })}`}
+    >
+      <ProTable<ServiceModule.ResponseBody>
+        actionRef={ref}
+        rowKey="id"
+        columns={columns}
+        request={fetchList}
+        toolBarRender={() => [
+          <Button type="primary" onClick={() => history.push(`/service/create`)}>
+            <PlusOutlined />
+            {formatMessage({ id: 'component.global.create' })}
+          </Button>,
+        ]}
+      />
+    </PageHeaderWrapper>
+  );
+};
 
 export default Page;
diff --git a/web/src/pages/Service/components/Step1.tsx b/web/src/pages/Service/components/Step1.tsx
index d1f508d..fd805ba 100644
--- a/web/src/pages/Service/components/Step1.tsx
+++ b/web/src/pages/Service/components/Step1.tsx
@@ -42,30 +42,26 @@ const Step1: React.FC<ServiceModule.Step1PassProps> = ({
     fetchUpstreamList().then(({ data }) => setList(data));
   }, []);
 
-  return <>
-    <Form {...FORM_LAYOUT} form={form}>
-      <Form.Item
-        name="name"
-        label={formatMessage({ id: 'component.global.name' })}
-      >
-        <Input disabled={disabled} />
-      </Form.Item>
-      <Form.Item
-        name="desc"
-        label={formatMessage({ id: 'component.global.description' })}
-      >
-        <Input.TextArea disabled={disabled} />
-      </Form.Item>
-    </Form>
-    <UpstreamForm
-      ref={upstreamRef}
-      form={upstreamForm}
-      disabled={disabled}
-      list={list}
-      showSelector
-      key={1}
-    />
-  </>
-}
+  return (
+    <>
+      <Form {...FORM_LAYOUT} form={form}>
+        <Form.Item name="name" label={formatMessage({ id: 'component.global.name' })}>
+          <Input disabled={disabled} />
+        </Form.Item>
+        <Form.Item name="desc" label={formatMessage({ id: 'component.global.description' })}>
+          <Input.TextArea disabled={disabled} />
+        </Form.Item>
+      </Form>
+      <UpstreamForm
+        ref={upstreamRef}
+        form={upstreamForm}
+        disabled={disabled}
+        list={list}
+        showSelector
+        key={1}
+      />
+    </>
+  );
+};
 
 export default Step1;
diff --git a/web/src/pages/Service/locales/en-US.ts b/web/src/pages/Service/locales/en-US.ts
index 2923865..cb26341 100644
--- a/web/src/pages/Service/locales/en-US.ts
+++ b/web/src/pages/Service/locales/en-US.ts
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 export default {
-    'page.service.steps.stepTitle.basicInformation': 'Basic Information',
-    'page.service.steps.stepTitle.pluginConfig': 'Plugin Config',
-    'page.service.steps.stepTitle.preview': 'Preview',
-}
+  'page.service.steps.stepTitle.basicInformation': 'Basic Information',
+  'page.service.steps.stepTitle.pluginConfig': 'Plugin Config',
+  'page.service.steps.stepTitle.preview': 'Preview',
+};
diff --git a/web/src/pages/Service/locales/zh-CN.ts b/web/src/pages/Service/locales/zh-CN.ts
index 53fda03..4050259 100644
--- a/web/src/pages/Service/locales/zh-CN.ts
+++ b/web/src/pages/Service/locales/zh-CN.ts
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 export default {
-    'page.service.steps.stepTitle.basicInformation': '基本信息',
-    'page.service.steps.stepTitle.pluginConfig': '插件配置',
-    'page.service.steps.stepTitle.preview': '预览',
-}
+  'page.service.steps.stepTitle.basicInformation': '基本信息',
+  'page.service.steps.stepTitle.pluginConfig': '插件配置',
+  'page.service.steps.stepTitle.preview': '预览',
+};
diff --git a/web/src/pages/Service/service.ts b/web/src/pages/Service/service.ts
index 1b541b2..bda706e 100644
--- a/web/src/pages/Service/service.ts
+++ b/web/src/pages/Service/service.ts
@@ -47,7 +47,8 @@ export const update = (serviceId: string, data: ServiceModule.Entity) =>
     data,
   });
 
-export const remove = (serviceId: string) => request(`/services/${serviceId}`, { method: 'DELETE' });
+export const remove = (serviceId: string) =>
+  request(`/services/${serviceId}`, { method: 'DELETE' });
 
 export const fetchItem = (serviceId: number) =>
-  request(`/services/${serviceId}`).then((data) => (data));
+  request(`/services/${serviceId}`).then((data) => data);
diff --git a/web/src/pages/Service/typing.d.ts b/web/src/pages/Service/typing.d.ts
index a9e52d0..3be9c32 100644
--- a/web/src/pages/Service/typing.d.ts
+++ b/web/src/pages/Service/typing.d.ts
@@ -15,33 +15,32 @@
  * limitations under the License.
  */
 declare namespace ServiceModule {
-
-    type Entity = {
-        name: string;
-        desc: string;
-        upstream: any;
-        upstream_id: string;
-        labels: string;
-        enable_websocket: boolean;
-        plugins: {
-            [name: string]: any;
-        };
+  type Entity = {
+    name: string;
+    desc: string;
+    upstream: any;
+    upstream_id: string;
+    labels: string;
+    enable_websocket: boolean;
+    plugins: {
+      [name: string]: any;
     };
+  };
 
-    type ResponseBody = {
-        id: string,
-        plugins: Record<string, any>,
-        upstream_id: string,
-        upstream: Record<string, any>,
-        name: string,
-        desc: string,
-        enable_websocket: boolean,
-    }
+  type ResponseBody = {
+    id: string;
+    plugins: Record<string, any>;
+    upstream_id: string;
+    upstream: Record<string, any>;
+    name: string;
+    desc: string;
+    enable_websocket: boolean;
+  };
 
-    type Step1PassProps = {
-        form: FormInstance;
-        upstreamForm: FormInstance;
-        disabled?: boolean;
-        upstreamRef: any;
-    };
+  type Step1PassProps = {
+    form: FormInstance;
+    upstreamForm: FormInstance;
+    disabled?: boolean;
+    upstreamRef: any;
+  };
 }
diff --git a/web/src/pages/Upstream/Create.tsx b/web/src/pages/Upstream/Create.tsx
index 09e14de..2840b8f 100644
--- a/web/src/pages/Upstream/Create.tsx
+++ b/web/src/pages/Upstream/Create.tsx
@@ -54,9 +54,9 @@ const Page: React.FC = (props) => {
         notification.success({
           message: `${
             id
-              ? formatMessage({ id: 'upstream.create.edit' })
-              : formatMessage({ id: 'upstream.create.create' })
-          } ${formatMessage({ id: 'upstream.create.upstream.successfully' })}`,
+              ? formatMessage({ id: 'page.upstream.create.edit' })
+              : formatMessage({ id: 'page.upstream.create.create' })
+          } ${formatMessage({ id: 'page.upstream.create.upstream.successfully' })}`,
         });
         history.replace('/upstream/list');
       });
@@ -77,11 +77,11 @@ const Page: React.FC = (props) => {
 
   return (
     <>
-      <PageContainer title={formatMessage({ id: 'upstream.create.create' })}>
+      <PageContainer title={formatMessage({ id: 'page.upstream.create.create' })}>
         <Card bordered={false}>
           <Steps current={step - 1} style={{ marginBottom: 30 }}>
-            <Steps.Step title={formatMessage({ id: 'upstream.create.basic.info' })} />
-            <Steps.Step title={formatMessage({ id: 'upstream.create.preview' })} />
+            <Steps.Step title={formatMessage({ id: 'page.upstream.create.basic.info' })} />
+            <Steps.Step title={formatMessage({ id: 'page.upstream.create.preview' })} />
           </Steps>
 
           {step === 1 && <Step1 form={form1} upstreamRef={upstreamRef} />}
diff --git a/web/src/pages/Upstream/List.tsx b/web/src/pages/Upstream/List.tsx
index 1f3d80e..5af67af 100644
--- a/web/src/pages/Upstream/List.tsx
+++ b/web/src/pages/Upstream/List.tsx
@@ -31,27 +31,27 @@ const Page: React.FC = () => {
 
   const columns: ProColumns<UpstreamModule.ResponseBody>[] = [
     {
-      title: formatMessage({ id: 'upstream.list.name' }),
+      title: formatMessage({ id: 'page.upstream.list.name' }),
       dataIndex: 'name',
     },
     {
-      title: formatMessage({ id: 'upstream.list.type' }),
+      title: formatMessage({ id: 'page.upstream.list.type' }),
       dataIndex: 'type',
       hideInSearch: true,
     },
     {
-      title: formatMessage({ id: 'upstream.list.description' }),
+      title: formatMessage({ id: 'page.upstream.list.description' }),
       dataIndex: 'desc',
       hideInSearch: true,
     },
     {
-      title: formatMessage({ id: 'upstream.list.edit.time' }),
+      title: formatMessage({ id: 'page.upstream.list.edit.time' }),
       dataIndex: 'update_time',
       hideInSearch: true,
       render: (text) => timestampToLocaleString(text as number),
     },
     {
-      title: formatMessage({ id: 'upstream.list.operation' }),
+      title: formatMessage({ id: 'page.upstream.list.operation' }),
       valueType: 'option',
       hideInSearch: true,
       render: (_, record) => (
@@ -61,16 +61,16 @@ const Page: React.FC = () => {
             style={{ marginRight: 10 }}
             onClick={() => history.push(`/upstream/${record.id}/edit`)}
           >
-            {formatMessage({ id: 'upstream.list.edit' })}
+            {formatMessage({ id: 'page.upstream.list.edit' })}
           </Button>
           <Popconfirm
-            title={formatMessage({ id: 'upstream.list.confirm.delete' })}
-            okText={formatMessage({ id: 'upstream.list.confirm' })}
-            cancelText={formatMessage({ id: 'upstream.list.cancel' })}
+            title={formatMessage({ id: 'page.upstream.list.confirm.delete' })}
+            okText={formatMessage({ id: 'page.upstream.list.confirm' })}
+            cancelText={formatMessage({ id: 'page.upstream.list.cancel' })}
             onConfirm={() => {
               remove(record.id!).then(() => {
                 notification.success({
-                  message: formatMessage({ id: 'upstream.list.delete.successfully' }),
+                  message: formatMessage({ id: 'page.upstream.list.delete.successfully' }),
                 });
                 /* eslint-disable no-unused-expressions */
                 ref.current?.reload();
@@ -78,7 +78,7 @@ const Page: React.FC = () => {
             }}
           >
             <Button type="primary" danger>
-              {formatMessage({ id: 'upstream.list.delete' })}
+              {formatMessage({ id: 'page.upstream.list.delete' })}
             </Button>
           </Popconfirm>
         </>
@@ -87,12 +87,16 @@ const Page: React.FC = () => {
   ];
 
   return (
-    <PageContainer title={formatMessage({ id: 'upstream.list' })}>
+    <PageContainer title={formatMessage({ id: 'page.upstream.list' })}>
       <ProTable<UpstreamModule.ResponseBody>
         actionRef={ref}
         columns={columns}
         rowKey="id"
         request={fetchList}
+        search={{
+          searchText: formatMessage({ id: 'component.global.search' }),
+          resetText: formatMessage({ id: 'component.global.reset' }),
+        }}
         toolBarRender={() => [
           <Button type="primary" onClick={() => history.push(`/upstream/create`)}>
             <PlusOutlined />
diff --git a/web/src/pages/Upstream/components/Step1.tsx b/web/src/pages/Upstream/components/Step1.tsx
index 1e6b4f6..79b8659 100644
--- a/web/src/pages/Upstream/components/Step1.tsx
+++ b/web/src/pages/Upstream/components/Step1.tsx
@@ -40,19 +40,19 @@ const Step1: React.FC<Props> = ({ form, disabled, upstreamRef }) => {
     <>
       <Form labelCol={{ span: 3 }} form={form} initialValues={DEFAULT_UPSTREAM}>
         <Form.Item
-          label={formatMessage({ id: 'upstream.step.name' })}
+          label={formatMessage({ id: 'page.upstream.step.name' })}
           name="name"
           rules={[{ required: true }]}
-          extra={formatMessage({ id: 'upstream.step.name.should.unique' })}
+          extra={formatMessage({ id: 'page.upstream.step.name.should.unique' })}
         >
           <Input
-            placeholder={formatMessage({ id: 'upstream.step.input.upstream.name' })}
+            placeholder={formatMessage({ id: 'page.upstream.step.input.upstream.name' })}
             disabled={disabled}
           />
         </Form.Item>
-        <Form.Item label={formatMessage({ id: 'upstream.step.description' })} name="desc">
+        <Form.Item label={formatMessage({ id: 'page.upstream.step.description' })} name="desc">
           <Input.TextArea
-            placeholder={formatMessage({ id: 'upstream.step.input.description' })}
+            placeholder={formatMessage({ id: 'page.upstream.step.input.description' })}
             disabled={disabled}
           />
         </Form.Item>
diff --git a/web/src/pages/Upstream/locales/en-US.ts b/web/src/pages/Upstream/locales/en-US.ts
index a339961..e94583f 100644
--- a/web/src/pages/Upstream/locales/en-US.ts
+++ b/web/src/pages/Upstream/locales/en-US.ts
@@ -15,80 +15,89 @@
  * limitations under the License.
  */
 export default {
-  'upstream.step.backend.server.domain.or.ip': 'Backend Server Domain Name/IP',
-  'upstream.step.domain.name.default.analysis':
+  'page.upstream.step.select.upstream': 'Select Upstream',
+  'page.upstream.step.select.upstream.select.option': 'Manual fill',
+  'page.upstream.form.item-label.node.domain.or.ip': 'Node Domain/IP',
+  'page.upstream.step.backend.server.domain.or.ip': 'Backend Server Domain Name/IP',
+  'page.upstream.form.item.extra-message.node.domain.or.ip':
     'When using domain name, it will analysis local: /etc/resolv.conf by default, if weight is 0, then fusing this node',
-  'upstream.step.input.domain.name.or.ip': 'Please input domain name/IP',
-  'upstream.step.domain.name.or.ip.rule': 'Only letters, numbers and . are supported',
-  'upstream.step.domain.name.or.ip': 'Domain Name/IP',
-  'upstream.step.input.port': 'Please input port number',
-  'upstream.step.port': 'Port Number',
-  'upstream.step.input.weight': 'Please input weight',
-  'upstream.step.weight': 'Weight',
-  'upstream.step.create': 'Create',
-  'upstream.step.name': 'Name',
-  'upstream.step.name.should.unique': 'Name should be unique',
-  'upstream.step.input.upstream.name': 'Please input upstream name',
-  'upstream.step.description': 'Description',
-  'upstream.step.input.description': 'Please input description',
-  'upstream.step.type': 'Type',
-  'upstream.step.pass-host': 'Pass Host',
-  'upstream.step.pass-host.tips': 'When selecting node, there can only be ONE node in node list.',
-  'upstream.step.pass-host.pass': 'pass',
-  'upstream.step.pass-host.node': 'node',
-  'upstream.step.pass-host.rewrite': 'rewrite',
-  'upstream.step.pass-host.upstream_host': 'Upstream Host',
-  'upstream.step.connect.timeout': 'Connect Timeout',
-  'upstream.step.input.connect.timeout': 'Please input connect timeout',
-  'upstream.step.send.timeout': 'Send Timeout',
-  'upstream.step.input.send.timeout': 'Please input send timeout',
-  'upstream.step.read.timeout': 'Read Timeout',
-  'upstream.step.input.read.timeout': 'Please input read timeout',
-  'upstream.step.healthy.check': 'Upstream Healthy Check',
-  'upstream.step.healthy.checks.healthy': 'Healthy',
-  'upstream.step.healthy.checks.unhealthy': 'Unhealthy',
-  'upstream.step.healthy.checks.active': 'Upstream Healthy Check Active',
-  'upstream.step.healthy.checks.active.timeout': 'Timeout',
-  'upstream.step.input.healthy.checks.active.timeout': 'Please input timeout',
-  'upstream.step.healthy.checks.active.http_path': 'HttpPath',
-  'upstream.step.input.healthy.checks.active.http_path': 'HttpPath',
-  'upstream.step.healthy.checks.active.port': "Port",
-  'upstream.step.input.healthy.checks.active.port': 'Please input port',
-  'upstream.step.healthy.checks.active.host': 'Host',
-  'upstream.step.input.healthy.checks.active.host': 'Please input Host',
-  'upstream.step.healthy.checks.active.interval': 'Interval',
-  'upstream.step.input.healthy.checks.active.interval': 'Please input Interval',
-  'upstream.step.healthy.checks.successes': 'Successes',
-  'upstream.step.input.healthy.checks.successes': 'Please input successes',
-  'upstream.step.healthy.checks.http_failures': 'HttpFailures',
-  'upstream.step.input.healthy.checks.http_failures': 'Please input httpFailures',
-  'upstream.step.healthy.checks.active.req_headers': 'req_headers',
-  'upstream.step.input.healthy.checks.active.req_headers': 'Please input req_headers',
-  'upstream.step.healthy.checks.passive': 'Passive',
-  'upstream.step.healthy.checks.passive.http_statuses': 'http_statuses',
-  'upstream.step.input.healthy.checks.passive.http_statuses': 'Please input http_statuses',
-  'upstream.step.healthy.checks.passive.tcp_failures': 'tcp_failures',
-  'upstream.step.input.healthy.checks.passive.tcp_failures': 'Please input tcp_failures',
-  'upstream.notificationMessage.enableHealthCheckFirst': 'Please enable health check first.',
+  'page.upstream.step.input.domain.name.or.ip': 'Please input domain name/IP',
+  'page.upstream.step.domain.name.or.ip.rule': 'Only letters, numbers and . are supported',
+  'page.upstream.step.domain.name.or.ip': 'Domain Name/IP',
+  'page.upstream.step.input.port': 'Please input port number',
+  'page.upstream.step.port': 'Port Number',
+  'page.upstream.step.input.weight': 'Please input weight',
+  'page.upstream.step.weight': 'Weight',
+  'page.upstream.step.create': 'Create',
+  'page.upstream.step.name': 'Name',
+  'page.upstream.step.name.should.unique': 'Name should be unique',
+  'page.upstream.step.input.upstream.name': 'Please input upstream name',
+  'page.upstream.step.description': 'Description',
+  'page.upstream.step.input.description': 'Please input description',
+  'page.upstream.step.type': 'Type',
+  'page.upstream.step.create.node': 'Create Node',
+  'page.upstream.step.pass-host': 'Pass Host',
+  'page.upstream.step.pass-host.tips':
+    'When selecting node, there can only be ONE node in node list.',
+  'page.upstream.step.pass-host.pass': 'pass',
+  'page.upstream.step.pass-host.node': 'node',
+  'page.upstream.step.pass-host.rewrite': 'rewrite',
+  'page.upstream.step.pass-host.upstream_host': 'Upstream Host',
+  'page.upstream.step.connect.timeout': 'Connect Timeout',
+  'page.upstream.step.input.connect.timeout': 'Please input connect timeout',
+  'page.upstream.step.send.timeout': 'Send Timeout',
+  'page.upstream.step.input.send.timeout': 'Please input send timeout',
+  'page.upstream.step.read.timeout': 'Read Timeout',
+  'page.upstream.step.input.read.timeout': 'Please input read timeout',
+  'page.upstream.step.healthyCheck.healthy.check': 'Health Check',
+  'page.upstream.step.healthyCheck.healthy': 'Healthy',
+  'page.upstream.step.healthyCheck.unhealthy': 'Unhealthy',
+  'page.upstream.step.healthyCheck.healthy.status': 'Healthy Status',
+  'page.upstream.step.healthyCheck.unhealthyStatus': 'Unhealthy Status',
+  'page.upstream.step.healthyCheck.active': 'Active',
+  'page.upstream.step.healthyCheck.active.timeout': 'Timeout',
+  'page.upstream.step.input.healthyCheck.active.timeout': 'Please input timeout',
+  'page.upstream.step.healthyCheck.active.http_path': 'HTTP Path',
+  'page.upstream.step.input.healthyCheck.active.http_path': 'Please input HTTP path',
+  'page.upstream.step.healthyCheck.activePort': 'Port',
+  'page.upstream.step.input.healthyCheck.activePort': 'Port',
+  'page.upstream.step.healthyCheck.activeHost': 'Host',
+  'page.upstream.step.input.healthyCheck.activeHost': 'Please input active host',
+  'page.upstream.step.healthyCheck.activeInterval': 'Interval',
+  'page.upstream.step.input.healthyCheck.activeInterval': 'Please input interval',
+  'page.upstream.step.healthyCheck.successes': 'Successes',
+  'page.upstream.step.input.healthyCheck.successes': 'Please input successes',
+  'page.upstream.step.healthyCheck.http_failures': 'HTTP Failures',
+  'page.upstream.step.healthyCheck.active.create.req_headers': 'Create Request Headers',
+  'page.upstream.step.input.healthyCheck.http_failures': 'Please input http failures',
+  'page.upstream.step.healthyCheck.active.req_headers': 'Request Headers',
+  'page.upstream.step.input.healthyCheck.active.req_headers': 'Please input request headers',
+  'page.upstream.step.healthyCheck.passive': 'Passive',
+  'page.upstream.step.healthyCheck.passive.create.http_statuses': 'Create HTTP Status',
+  'page.upstream.step.healthyCheck.passive.http_statuses': 'HTTP Status',
+  'page.upstream.step.input.healthyCheck.passive.http_statuses': 'Please input http status',
+  'page.upstream.step.healthyCheck.passive.tcp_failures': 'TCP Failures',
+  'page.upstream.step.input.healthyCheck.passive.tcp_failures': 'Please input TCP failures',
+  'page.upstream.notificationMessage.enableHealthCheckFirst': 'Please enable health check first.',
 
-  'upstream.create.edit': 'Edit',
-  'upstream.create.create': 'Create',
-  'upstream.create.upstream.successfully': 'upstream successfully',
-  'upstream.create.basic.info': 'Basic Information',
-  'upstream.create.preview': 'Preview',
+  'page.upstream.create.edit': 'Edit',
+  'page.upstream.create.create': 'Create',
+  'page.upstream.create.upstream.successfully': 'upstream successfully',
+  'page.upstream.create.basic.info': 'Basic Information',
+  'page.upstream.create.preview': 'Preview',
 
-  'upstream.list.name': 'Name',
-  'upstream.list.type': 'Type',
-  'upstream.list.description': 'Description',
-  'upstream.list.edit.time': 'Edit Time',
-  'upstream.list.operation': 'Operation',
-  'upstream.list.edit': 'Edit',
-  'upstream.list.confirm.delete': 'Are you sure to delete ?',
-  'upstream.list.confirm': 'Confirm',
-  'upstream.list.cancel': 'Cancel',
-  'upstream.list.delete.successfully': 'Delete successfully',
-  'upstream.list.delete': 'Delete',
-  'upstream.list': 'Upstream List',
-  'upstream.list.input': 'Please input',
-  'upstream.list.create': 'Create',
+  'page.upstream.list.name': 'Name',
+  'page.upstream.list.type': 'Type',
+  'page.upstream.list.description': 'Description',
+  'page.upstream.list.edit.time': 'Edit Time',
+  'page.upstream.list.operation': 'Operation',
+  'page.upstream.list.edit': 'Edit',
+  'page.upstream.list.confirm.delete': 'Are you sure to delete ?',
+  'page.upstream.list.confirm': 'Confirm',
+  'page.upstream.list.cancel': 'Cancel',
+  'page.upstream.list.delete.successfully': 'Delete successfully',
+  'page.upstream.list.delete': 'Delete',
+  'page.upstream.list': 'Upstream List',
+  'page.upstream.list.input': 'Please input',
+  'page.upstream.list.create': 'Create',
 };
diff --git a/web/src/pages/Upstream/locales/zh-CN.ts b/web/src/pages/Upstream/locales/zh-CN.ts
index 44bae36..335d378 100644
--- a/web/src/pages/Upstream/locales/zh-CN.ts
+++ b/web/src/pages/Upstream/locales/zh-CN.ts
@@ -15,80 +15,88 @@
  * limitations under the License.
  */
 export default {
-  'upstream.step.backend.server.domain.or.ip': '后端服务域名/IP',
-  'upstream.step.domain.name.default.analysis':
+  'page.upstream.step.select.upstream': '选择上游',
+  'page.upstream.step.select.upstream.select.option': '手动填写',
+  'page.upstream.form.item-label.node.domain.or.ip': '节点域名/IP',
+  'page.upstream.step.backend.server.domain.or.ip': '后端服务域名/IP',
+  'page.upstream.form.item.extra-message.node.domain.or.ip':
     '使用域名时,默认解析本地 /etc/resolv.conf;权重为0则熔断该节点',
-  'upstream.step.input.domain.name.or.ip': '请输入域名/IP',
-  'upstream.step.domain.name.or.ip.rule': '仅支持字母、数字和 . ',
-  'upstream.step.domain.name.or.ip': '域名/IP',
-  'upstream.step.input.port': '请输入端口号',
-  'upstream.step.port': '端口号',
-  'upstream.step.input.weight': '请输入权重',
-  'upstream.step.weight': '权重',
-  'upstream.step.create': '创建',
-  'upstream.step.name': '名称',
-  'upstream.step.name.should.unique': '名称需全局唯一',
-  'upstream.step.input.upstream.name': '请输入上游名称',
-  'upstream.step.description': '描述',
-  'upstream.step.input.description': '请输入描述',
-  'upstream.step.type': '类型',
-  'upstream.step.pass-host': '传递域名',
-  'upstream.step.pass-host.tips': '当选择节点时,节点域名只能有一条数据。',
-  'upstream.step.pass-host.pass': '透传',
-  'upstream.step.pass-host.node': '节点',
-  'upstream.step.pass-host.rewrite': '重写',
-  'upstream.step.pass-host.upstream_host': '上游域名',
-  'upstream.step.connect.timeout': '连接超时',
-  'upstream.step.input.connect.timeout': '请输入连接超时时间',
-  'upstream.step.send.timeout': '发送超时',
-  'upstream.step.input.send.timeout': '请输入发送超时时间',
-  'upstream.step.read.timeout': '接收超时',
-  'upstream.step.input.read.timeout': '请输入接收超时时间',
-  'upstream.step.healthy.check': '上游健康检查',
-  'upstream.step.healthy.checks.healthy': '健康',
-  'upstream.step.healthy.checks.unhealthy': '不健康',
-  'upstream.step.healthy.checks.active': '探活健康检查',
-  'upstream.step.healthy.checks.active.timeout': '超时时间',
-  'upstream.step.input.healthy.checks.active.timeout': '请输入超时时间',
-  'upstream.step.healthy.checks.active.http_path': '路径',
-  'upstream.step.input.healthy.checks.active.http_path': '请输入路径',
-  'upstream.step.healthy.checks.active.port': "端口",
-  'upstream.step.input.healthy.checks.active.port': '请输入端口',
-  'upstream.step.healthy.checks.active.host': '域名',
-  'upstream.step.input.healthy.checks.active.host': '请输入域名',
-  'upstream.step.healthy.checks.active.interval': '间隔',
-  'upstream.step.input.healthy.checks.active.interval': '请输入间隔',
-  'upstream.step.healthy.checks.successes': '成功次数',
-  'upstream.step.input.healthy.checks.successes': '请输入成功次数',
-  'upstream.step.healthy.checks.http_failures': '失败次数',
-  'upstream.step.input.healthy.checks.http_failures': '请输入失败次数',
-  'upstream.step.healthy.checks.active.req_headers': '请求头',
-  'upstream.step.input.healthy.checks.active.req_headers': '请输入请求头',
-  'upstream.step.healthy.checks.passive': '被动健康检查',
-  'upstream.step.healthy.checks.passive.http_statuses': '状态码',
-  'upstream.step.input.healthy.checks.passive.http_statuses': '请输入状态码',
-  'upstream.step.healthy.checks.passive.tcp_failures': 'tcp失败次数',
-  'upstream.step.input.healthy.checks.passive.tcp_failures': '请输入tcp失败次数',
-  'upstream.notificationMessage.enableHealthCheckFirst': '请先启用探活健康检查。',
+  'page.upstream.step.input.domain.name.or.ip': '请输入域名/IP',
+  'page.upstream.step.domain.name.or.ip.rule': '仅支持字母、数字和 . ',
+  'page.upstream.step.domain.name.or.ip': '域名/IP',
+  'page.upstream.step.input.port': '请输入端口号',
+  'page.upstream.step.port': '端口号',
+  'page.upstream.step.input.weight': '请输入权重',
+  'page.upstream.step.weight': '权重',
+  'page.upstream.step.create': '创建',
+  'page.upstream.step.name': '名称',
+  'page.upstream.step.name.should.unique': '名称需全局唯一',
+  'page.upstream.step.input.upstream.name': '请输入上游名称',
+  'page.upstream.step.description': '描述',
+  'page.upstream.step.input.description': '请输入描述',
+  'page.upstream.step.type': '类型',
+  'page.upstream.step.create.node': '创建节点',
+  'page.upstream.step.pass-host': '传递域名',
+  'page.upstream.step.pass-host.tips': '当选择节点时,节点域名只能有一条数据。',
+  'page.upstream.step.pass-host.pass': '透传',
+  'page.upstream.step.pass-host.node': '节点',
+  'page.upstream.step.pass-host.rewrite': '重写',
+  'page.upstream.step.pass-host.upstream_host': '上游域名',
+  'page.upstream.step.connect.timeout': '连接超时',
+  'page.upstream.step.input.connect.timeout': '请输入连接超时时间',
+  'page.upstream.step.send.timeout': '发送超时',
+  'page.upstream.step.input.send.timeout': '请输入发送超时时间',
+  'page.upstream.step.read.timeout': '接收超时',
+  'page.upstream.step.input.read.timeout': '请输入接收超时时间',
+  'page.upstream.step.healthyCheck.healthy.check': '健康检查',
+  'page.upstream.step.healthyCheck.healthy': '健康',
+  'page.upstream.step.healthyCheck.unhealthy': '不健康',
+  'page.upstream.step.healthyCheck.healthy.status': '健康状态',
+  'page.upstream.step.healthyCheck.unhealthyStatus': '不健康状态',
+  'page.upstream.step.healthyCheck.active': '主动',
+  'page.upstream.step.healthyCheck.active.timeout': '超时时间',
+  'page.upstream.step.input.healthyCheck.active.timeout': '请输入超时时间',
+  'page.upstream.step.healthyCheck.active.http_path': '路径',
+  'page.upstream.step.input.healthyCheck.active.http_path': '请输入路径',
+  'page.upstream.step.healthyCheck.activePort': '端口',
+  'page.upstream.step.input.healthyCheck.activePort': '请输入端口',
+  'page.upstream.step.healthyCheck.activeHost': '域名',
+  'page.upstream.step.input.healthyCheck.activeHost': '请输入域名',
+  'page.upstream.step.healthyCheck.activeInterval': '间隔',
+  'page.upstream.step.input.healthyCheck.activeInterval': '请输入间隔',
+  'page.upstream.step.healthyCheck.successes': '成功次数',
+  'page.upstream.step.input.healthyCheck.successes': '请输入成功次数',
+  'page.upstream.step.healthyCheck.http_failures': '失败次数',
+  'page.upstream.step.healthyCheck.active.create.req_headers': '创建请求头',
+  'page.upstream.step.input.healthyCheck.http_failures': '请输入失败次数',
+  'page.upstream.step.healthyCheck.active.req_headers': '请求头',
+  'page.upstream.step.input.healthyCheck.active.req_headers': '请输入请求头',
+  'page.upstream.step.healthyCheck.passive': '被动',
+  'page.upstream.step.healthyCheck.passive.create.http_statuses': '创建状态码',
+  'page.upstream.step.healthyCheck.passive.http_statuses': '状态码',
+  'page.upstream.step.input.healthyCheck.passive.http_statuses': '请输入状态码',
+  'page.upstream.step.healthyCheck.passive.tcp_failures': 'tcp失败次数',
+  'page.upstream.step.input.healthyCheck.passive.tcp_failures': '请输入tcp失败次数',
+  'page.upstream.notificationMessage.enableHealthCheckFirst': '请先启用探活健康检查。',
 
-  'upstream.create.edit': '编辑',
-  'upstream.create.create': '创建',
-  'upstream.create.upstream.successfully': '上游成功',
-  'upstream.create.basic.info': '基础信息',
-  'upstream.create.preview': '预览',
+  'page.upstream.create.edit': '编辑',
+  'page.upstream.create.create': '创建',
+  'page.upstream.create.upstream.successfully': '上游成功',
+  'page.upstream.create.basic.info': '基础信息',
+  'page.upstream.create.preview': '预览',
 
-  'upstream.list.name': '名称',
-  'upstream.list.type': '类型',
-  'upstream.list.description': '描述',
-  'upstream.list.edit.time': '编辑时间',
-  'upstream.list.operation': '操作',
-  'upstream.list.edit': '编辑',
-  'upstream.list.confirm.delete': '确定删除该条记录吗?',
-  'upstream.list.confirm': '确定',
-  'upstream.list.cancel': '取消',
-  'upstream.list.delete.successfully': '删除记录成功',
-  'upstream.list.delete': '删除',
-  'upstream.list': '上游列表',
-  'upstream.list.input': '请输入',
-  'upstream.list.create': '创建',
+  'page.upstream.list.name': '名称',
+  'page.upstream.list.type': '类型',
+  'page.upstream.list.description': '描述',
+  'page.upstream.list.edit.time': '编辑时间',
+  'page.upstream.list.operation': '操作',
+  'page.upstream.list.edit': '编辑',
+  'page.upstream.list.confirm.delete': '确定删除该条记录吗?',
+  'page.upstream.list.confirm': '确定',
+  'page.upstream.list.cancel': '取消',
+  'page.upstream.list.delete.successfully': '删除记录成功',
+  'page.upstream.list.delete': '删除',
+  'page.upstream.list': '上游列表',
+  'page.upstream.list.input': '请输入',
+  'page.upstream.list.create': '创建',
 };