diff --git a/omega-i18n/en/messages.json b/omega-i18n/en/messages.json
index 6421aee..59f222a 100644
--- a/omega-i18n/en/messages.json
+++ b/omega-i18n/en/messages.json
@@ -173,7 +173,7 @@
     "message": "Show advanced condition types"
   },
   "options_showConditionTypesAdvancedHelp": {
-    "message": "Unlocks new types of advanced but complicated switch conditions. For most senarios, the basic condition types should be enough, so this options is not recommended."
+    "message": "Unlocks new types of advanced but complicated switch conditions. For most senarios, the basic condition types should be enough, so this option is not recommended."
   },
   "options_quickSwitch": {
     "message": "Quick Switch"
@@ -346,6 +346,18 @@
   "options_group_pacScript": {
     "message": "PAC Script"
   },
+  "options_pacScriptLastUpdate": {
+    "message": "PAC script downloaded at $TIME$:",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "Jan 2, 2015 7:22:08 PM"
+      }
+    }
+  },
+  "options_pacScriptObsolete": {
+    "message": "PAC script is obsolete due to URL change. Press the download button above to update."
+  },
   "options_group_virtualProfile": {
     "message": "Virtual Profile"
   },
@@ -394,6 +406,18 @@
   "options_group_ruleListText": {
     "message": "Rule List Text"
   },
+  "options_ruleListLastUpdate": {
+    "message": "Rule list downloaded at $TIME$:",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "Jan 2, 2015 7:22:08 PM"
+      }
+    }
+  },
+  "options_ruleListObsolete": {
+    "message": "Rule list is obsolete due to URL change. Press the download button above to update."
+  },
   "options_group_switchRules": {
     "message": "Switch rules"
   },
diff --git a/omega-i18n/zh_CN/messages.json b/omega-i18n/zh_CN/messages.json
index eb83db3..3a43d52 100644
--- a/omega-i18n/zh_CN/messages.json
+++ b/omega-i18n/zh_CN/messages.json
@@ -346,6 +346,18 @@
   "options_group_pacScript": {
     "message": "PAC 脚本"
   },
+  "options_pacScriptLastUpdate": {
+    "message": "PAC 脚本最后更新时间:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "2015年1月2日 下午7:22:08"
+      }
+    }
+  },
+  "options_pacScriptObsolete": {
+    "message": "修改网址后尚未下载更新,因此脚本已经过时。请使用上方的更新按钮进行下载。"
+  },
   "options_group_virtualProfile": {
     "message": "虚情景模式"
   },
@@ -394,6 +406,18 @@
   "options_group_ruleListText": {
     "message": "规则列表正文"
   },
+  "options_ruleListLastUpdate": {
+    "message": "规则列表最后更新时间:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "2015年1月2日 下午7:22:08"
+      }
+    }
+  },
+  "options_ruleListObsolete": {
+    "message": "修改网址后尚未下载更新,因此规则列表已经过时。请使用上方的更新按钮进行下载。"
+  },
   "options_group_switchRules": {
     "message": "切换规则"
   },
diff --git a/omega-i18n/zh_HK/messages.json b/omega-i18n/zh_HK/messages.json
index 9e67a08..0ff7429 100644
--- a/omega-i18n/zh_HK/messages.json
+++ b/omega-i18n/zh_HK/messages.json
@@ -346,6 +346,18 @@
   "options_group_pacScript": {
     "message": "PAC 腳本"
   },
+  "options_pacScriptLastUpdate": {
+    "message": "PAC 指令碼最後更新時間:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "Jan 2, 2015 7:22:08 PM"
+      }
+    }
+  },
+  "options_pacScriptObsolete": {
+    "message": "修改網址後尚未下載更新,因此指令碼已經過時。請使用上方的更新按鈕進行下載。"
+  },
   "options_group_virtualProfile": {
     "message": "虛情景模式"
   },
@@ -394,6 +406,18 @@
   "options_group_ruleListText": {
     "message": "規則列表正文"
   },
+  "options_ruleListLastUpdate": {
+    "message": "規則列表最後更新時間:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "2015年1月2日 下午7:22:08"
+      }
+    }
+  },
+  "options_ruleListObsolete": {
+    "message": "修改網址後尚未下載更新,因此規則列表已經過時。請使用上方的更新按鈕進行下載。"
+  },
   "options_group_switchRules": {
     "message": "切換規則"
   },
diff --git a/omega-i18n/zh_TW/messages.json b/omega-i18n/zh_TW/messages.json
index 584b798..3d5d45a 100644
--- a/omega-i18n/zh_TW/messages.json
+++ b/omega-i18n/zh_TW/messages.json
@@ -346,6 +346,18 @@
   "options_group_pacScript": {
     "message": "PAC 指令碼"
   },
+  "options_pacScriptLastUpdate": {
+    "message": "PAC 指令碼最後更新時間:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "Jan 2, 2015 7:22:08 PM"
+      }
+    }
+  },
+  "options_pacScriptObsolete": {
+    "message": "修改網址後尚未下載更新,因此指令碼已經過時。請使用上方的更新按鈕進行下載。"
+  },
   "options_group_virtualProfile": {
     "message": "虛情景模式"
   },
@@ -394,6 +406,18 @@
   "options_group_ruleListText": {
     "message": "規則列表正文"
   },
+  "options_ruleListLastUpdate": {
+    "message": "規則列表最後更新時間:$TIME$",
+    "placeholders": {
+      "TIME": {
+        "content": "$1",
+        "example": "2015年1月2日 下午7:22:08"
+      }
+    }
+  },
+  "options_ruleListObsolete": {
+    "message": "修改網址後尚未下載更新,因此規則列表已經過時。請使用上方的更新按鈕進行下載。"
+  },
   "options_group_switchRules": {
     "message": "切換規則"
   },
diff --git a/omega-target/src/options.coffee b/omega-target/src/options.coffee
index 83fc92c..52c176b 100644
--- a/omega-target/src/options.coffee
+++ b/omega-target/src/options.coffee
@@ -506,6 +506,7 @@ class Options
         results[key] = @fetchUrl(url, opt_bypass_cache).then((data) =>
           profile = OmegaPac.Profiles.byKey(key, @_options)
           OmegaPac.Profiles.update(profile, data)
+          profile.lastUpdate = new Date().toISOString()
           OmegaPac.Profiles.updateRevision(profile)
           changes = {}
           changes[key] = profile
diff --git a/omega-web/bower.json b/omega-web/bower.json
index 9beaaf3..88c3741 100644
--- a/omega-web/bower.json
+++ b/omega-web/bower.json
@@ -62,7 +62,9 @@
     "angular-i18n": {
       "": [
         "angular-locale_en-us.js",
-        "angular-locale_zh-cn.js"
+        "angular-locale_zh-cn.js",
+        "angular-locale_zh-hk.js",
+        "angular-locale_zh-tw.js"
       ]
     },
     "angular-loader": {
diff --git a/omega-web/src/coffee/options.coffee b/omega-web/src/coffee/options.coffee
index b659d19..abd5f75 100644
--- a/omega-web/src/coffee/options.coffee
+++ b/omega-web/src/coffee/options.coffee
@@ -17,12 +17,29 @@ $script.ready ['angular-loader'], ->
     'omegaDecoration']
   $script.ready ['omega-pac'], ->
     $script 'js/omega.js', 'omega'
+
+  locales =
+    '': 'en-us'
+
+    'en': 'en-us'
+
+    'zh': 'zh-cn'
+    'zh-hans': 'zh-cn'
+    'zh-hant': 'zh-tw'
+    'zh-cn': 'zh-cn'
+    'zh-hk': 'zh-hk'
+    'zh-tw': 'zh-tw'
+
+  lang = navigator.language
+  lang1 = navigator.language?.split('-')[0] || ''
+  locale = locales[lang] || locales[lang1] || locales['']
+
   $script([
     'js/omega_target_web.js'
     'js/omega_decoration.js'
     'lib/angular-animate/angular-animate.min.js'
     'lib/angular-bootstrap/ui-bootstrap-tpls.min.js'
-    'lib/angular-i18n/angular-locale_en-us.js'
+    'lib/angular-i18n/angular-locale_' + locale + '.js'
     'lib/ngprogress/ngProgress.min.js'
     'lib/angular-ui-sortable/sortable.min.js'
     'lib/angular-ui-utils/validate.min.js'
diff --git a/omega-web/src/omega/controllers/pac_profile.coffee b/omega-web/src/omega/controllers/pac_profile.coffee
index ece0b89..8ed417e 100644
--- a/omega-web/src/omega/controllers/pac_profile.coffee
+++ b/omega-web/src/omega/controllers/pac_profile.coffee
@@ -14,6 +14,19 @@ angular.module('omega').controller 'PacProfileCtrl', ($scope) ->
   set = OmegaPac.Profiles.referencedBySet($scope.profile, $scope.options)
   $scope.referenced = Object.keys(set).length > 0
 
-  onProfileChange = (profile) ->
+  oldPacUrl = null
+  oldLastUpdate = null
+  oldPacScript = null
+  onProfileChange = (profile, oldProfile) ->
+    return unless profile and oldProfile
+    if profile.pacUrl != oldProfile.pacUrl
+      if profile.lastUpdate
+        oldPacUrl = oldProfile.pacUrl
+        oldLastUpdate = profile.lastUpdate
+        oldPacScript = oldProfile.pacScript
+        profile.lastUpdate = null
+      else if oldPacUrl and profile.pacUrl == oldPacUrl
+        profile.lastUpdate = oldLastUpdate
+        profile.pacScript = oldPacScript
     $scope.pacUrlIsFile = $scope.isFileUrl(profile.pacUrl)
   $scope.$watch 'profile', onProfileChange, true
diff --git a/omega-web/src/omega/controllers/switch_profile.coffee b/omega-web/src/omega/controllers/switch_profile.coffee
index 8515702..ac66be2 100644
--- a/omega-web/src/omega/controllers/switch_profile.coffee
+++ b/omega-web/src/omega/controllers/switch_profile.coffee
@@ -200,6 +200,22 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
 
   $scope.watchAndUpdateRevision 'options[attachedKey]'
 
+  oldSourceUrl = null
+  oldLastUpdate = null
+  oldRuleList = null
+  onAttachedChange = (attached, oldAttached) ->
+    return unless attached and oldAttached
+    if attached.sourceUrl != oldAttached.sourceUrl
+      if attached.lastUpdate
+        oldSourceUrl = oldAttached.sourceUrl
+        oldLastUpdate = attached.lastUpdate
+        oldRuleList = oldAttached.ruleList
+        attached.lastUpdate = null
+      else if oldSourceUrl and attached.sourceUrl == oldSourceUrl
+        attached.lastUpdate = oldLastUpdate
+        attached.ruleList = oldRuleList
+  $scope.$watch 'options[attachedKey]', onAttachedChange, true
+
   $scope.attachedOptions = {enabled: false}
   $scope.$watch 'profile.defaultProfileName', (name) ->
     $scope.attachedOptions.enabled = (name == $scope.attachedName)
diff --git a/omega-web/src/partials/profile_pac.jade b/omega-web/src/partials/profile_pac.jade
index b4e2268..494a339 100644
--- a/omega-web/src/partials/profile_pac.jade
+++ b/omega-web/src/partials/profile_pac.jade
@@ -1,18 +1,24 @@
-section.settings-group(ng-controller='PacProfileCtrl')
-  h3 {{'options_group_pacUrl' | tr}}
-  .width-limit(input-group-clear type='text' model='profile.pacUrl'
-    ng-pattern='referenced ? urlRegex : urlWithFile' controller='pacUrlCtrl.ctrl')
-  p.help-block {{'options_pacUrlHelp' | tr}}
-  .has-warning(ng-show='isFileUrl(profile.pacUrl) && !referenced')
-    p.help-block #[span.glyphicon.glyphicon-warning-sign] {{'options_pacUrlFile' | tr}}
-  .has-error(ng-show='isFileUrl(pacUrlCtrl.ctrl.$viewValue) && referenced')
-    p.help-block #[span.glyphicon.glyphicon-remove-sign] {{'options_pacUrlFile' | tr}}
-    p.help-block {{'options_pacUrlFileDisabled' | tr}}
-section.settings-group
-  h3 {{'options_group_pacScript' | tr}}
-  p
-    button.btn.btn-default(ng-disabled='!profile.pacUrl' ng-click='updateProfile(profile.name)'
-        ladda='updatingProfile[profile.name]' data-spinner-color="#000000")
-      | #[span.glyphicon.glyphicon-download-alt] {{'options_downloadProfileNow' | tr}}
-  textarea.monospace.form-control.width-limit(ng-model='profile.pacScript' rows=20
-    ng-disabled='!!profile.pacUrl')
+div(ng-controller='PacProfileCtrl')
+  section.settings-group
+    h3 {{'options_group_pacUrl' | tr}}
+    .width-limit(input-group-clear type='text' model='profile.pacUrl'
+      ng-pattern='referenced ? urlRegex : urlWithFile' controller='pacUrlCtrl.ctrl')
+    p.help-block {{'options_pacUrlHelp' | tr}}
+    .has-warning(ng-show='pacUrlIsFile && !referenced')
+      p.help-block #[span.glyphicon.glyphicon-warning-sign] {{'options_pacUrlFile' | tr}}
+    .has-error(ng-show='isFileUrl(pacUrlCtrl.ctrl.$viewValue) && referenced')
+      p.help-block #[span.glyphicon.glyphicon-remove-sign] {{'options_pacUrlFile' | tr}}
+      p.help-block {{'options_pacUrlFileDisabled' | tr}}
+    p(ng-show='profile.pacUrl && !pacUrlIsFile')
+      button.btn(ng-click='updateProfile(profile.name)'
+        ladda='updatingProfile[profile.name]' data-spinner-color="#000000"
+        ng-class='profile.pacUrl && !profile.lastUpdate ? "btn-primary" : "btn-default"')
+        | #[span.glyphicon.glyphicon-download-alt] {{'options_downloadProfileNow' | tr}}
+  section.settings-group(ng-hide='pacUrlIsFile')
+    h3 {{'options_group_pacScript' | tr}}
+    p.alert.alert-success.width-limit(ng-show='profile.pacUrl && profile.lastUpdate')
+      | {{'options_pacScriptLastUpdate' | tr:[(profile.lastUpdate | date:'medium')]}}
+    p.alert.alert-danger.width-limit(ng-show='profile.pacUrl && !profile.lastUpdate')
+      | {{'options_pacScriptObsolete' | tr}}
+    textarea.monospace.form-control.width-limit(ng-model='profile.pacScript' rows=20
+      ng-disabled='pacUrlCtrl.ctrl.$invalid || !!profile.pacUrl')
diff --git a/omega-web/src/partials/profile_switch.jade b/omega-web/src/partials/profile_switch.jade
index 082403a..7efdabf 100644
--- a/omega-web/src/partials/profile_switch.jade
+++ b/omega-web/src/partials/profile_switch.jade
@@ -120,11 +120,16 @@ div(ng-controller='SwitchProfileCtrl')
         .width-limit.inline-form-control(input-group-clear type='url' model='attached.sourceUrl'
           style='vertical-align: middle')
       p.help-block {{'options_ruleListUrlHelp' | tr}}
-  section.settings-group(ng-if='attached')
-    h3 {{'options_group_ruleListText' | tr}}
     p
       button.btn.btn-default(ng-disabled='!attached.sourceUrl' ng-click='updateProfile(attached.name)'
-          ladda='updatingProfile[attached.name]' data-spinner-color="#000000")
+          ladda='updatingProfile[attached.name]' data-spinner-color="#000000"
+          ng-class='attached.sourceUrl && !attached.lastUpdate ? "btn-primary" : "btn-default"')
         | #[span.glyphicon.glyphicon-download-alt] {{'options_downloadProfileNow' | tr}}
+  section.settings-group(ng-if='attached')
+    h3 {{'options_group_ruleListText' | tr}}
+    p.alert.alert-success.width-limit(ng-show='attached.sourceUrl && attached.lastUpdate')
+      | {{'options_ruleListLastUpdate' | tr:[(attached.lastUpdate | date:'medium')]}}
+    p.alert.alert-danger.width-limit(ng-show='attached.sourceUrl && !attached.lastUpdate')
+      | {{'options_ruleListObsolete' | tr}}
     textarea.monospace.form-control.width-limit(ng-model='attached.ruleList' rows=20
       ng-disabled='!!attached.sourceUrl')