aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/_locales/en/messages.json27
-rw-r--r--app/_locales/index.json19
-rw-r--r--app/_locales/it/messages.json2
-rw-r--r--app/_locales/ja/messages.json76
-rw-r--r--app/_locales/pt/messages.json2
-rw-r--r--app/_locales/sl/messages.json819
-rw-r--r--app/_locales/th/messages.json819
-rw-r--r--app/_locales/zh_TW/messages.json903
-rw-r--r--app/manifest.json2
-rw-r--r--app/scripts/background.js13
-rw-r--r--app/scripts/controllers/preferences.js5
-rw-r--r--app/scripts/lib/get-first-preferred-lang-code.js16
-rw-r--r--app/scripts/lib/setupRaven.js32
-rw-r--r--app/scripts/lib/tx-state-manager.js7
-rw-r--r--app/scripts/metamask-controller.js13
-rw-r--r--app/scripts/migrations/022.js39
-rw-r--r--app/scripts/migrations/023.js50
-rw-r--r--app/scripts/migrations/index.js2
-rw-r--r--app/scripts/popup.js126
-rw-r--r--app/scripts/vendor/raven.min.js3
20 files changed, 2876 insertions, 99 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index c64b7248b..3e469cf44 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -171,6 +171,9 @@
"customGas": {
"message": "Customize Gas"
},
+ "customToken": {
+ "message": "Custom Token"
+ },
"customize": {
"message": "Customize"
},
@@ -182,7 +185,7 @@
},
"decimal": {
"message": "Decimals of Precision"
- },
+ },
"defaultNetwork": {
"message": "The default network for Ether transactions is Main Net."
},
@@ -232,7 +235,7 @@
"done": {
"message": "Done"
},
- "downloadStatelogs": {
+ "downloadStateLogs": {
"message": "Download State Logs"
},
"dropped": {
@@ -415,6 +418,9 @@
"message": "JSON File",
"description": "format for importing an account"
},
+ "keepTrackTokens": {
+ "message": "Keep track of the tokens you’ve bought with your MetaMask account."
+ },
"kovan": {
"message": "Kovan Test Network"
},
@@ -424,6 +430,9 @@
"max": {
"message": "Max"
},
+ "learnMore": {
+ "message": "Learn more."
+ },
"lessThanMax": {
"message": "must be less than or equal to $1.",
"description": "helper for inputting hex as decimal input"
@@ -564,6 +573,9 @@
"pleaseReviewTransaction": {
"message": "Please review your transaction."
},
+ "popularTokens": {
+ "message": "Popular Tokens"
+ },
"privacyMsg": {
"message": "Privacy Policy"
},
@@ -659,6 +671,12 @@
"save": {
"message": "Save"
},
+ "reprice_title": {
+ "message": "Reprice Transaction"
+ },
+ "reprice_subtitle": {
+ "message": "Increase your gas price to attempt to overwrite and speed up your transaction"
+ },
"saveAsFile": {
"message": "Save as File",
"description": "Account export process"
@@ -702,6 +720,9 @@
"onlySendToEtherAddress": {
"message": "Only send ETH to an Ethereum address."
},
+ "searchTokens": {
+ "message": "Search Tokens"
+ },
"sendTokensAnywhere": {
"message": "Send Tokens to anyone with an Ethereum account"
},
@@ -869,7 +890,7 @@
},
"visitWebSite": {
"message": "Visit our web site"
- },
+ },
"warning": {
"message": "Warning"
},
diff --git a/app/_locales/index.json b/app/_locales/index.json
new file mode 100644
index 000000000..c085deb72
--- /dev/null
+++ b/app/_locales/index.json
@@ -0,0 +1,19 @@
+[
+ { "code": "de", "name": "German" },
+ { "code": "en", "name": "English" },
+ { "code": "es", "name": "Spanish" },
+ { "code": "fr", "name": "French" },
+ { "code": "hn", "name": "Hindi" },
+ { "code": "it", "name": "Italian" },
+ { "code": "ja", "name": "Japanese" },
+ { "code": "ko", "name": "Korean" },
+ { "code": "nl", "name": "Dutch" },
+ { "code": "ph", "name": "Tagalog" },
+ { "code": "pt", "name": "Portuguese" },
+ { "code": "ru", "name": "Russian" },
+ { "code": "sl", "name": "Slovenian" },
+ { "code": "th", "name": "Thai" },
+ { "code": "vi", "name": "Vietnamese" },
+ { "code": "zh_CN", "name": "Mandarin" },
+ { "code": "zh_TW", "name": "Taiwanese" }
+]
diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json
index f54ef98ca..ef3ed4025 100644
--- a/app/_locales/it/messages.json
+++ b/app/_locales/it/messages.json
@@ -223,7 +223,7 @@
"done": {
"message": "Finito"
},
- "downloadStatelogs": {
+ "downloadStateLogs": {
"message": "Scarica i log di Stato"
},
"edit": {
diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json
index bab8d3b95..d9762a3e9 100644
--- a/app/_locales/ja/messages.json
+++ b/app/_locales/ja/messages.json
@@ -14,6 +14,9 @@
"address": {
"message": "アドレス"
},
+ "addCustomToken": {
+ "message": "カスタムトークンを追加"
+ },
"addToken": {
"message": "トークンを追加"
},
@@ -63,11 +66,14 @@
"message": "Coinbaseで購入"
},
"buyCoinbaseExplainer": {
- "message": "Coinbaseは、世界で最もポピュラーなBitcoin、Ethereum、そしてLitecoinの取引所です。"
+ "message": "Coinbaseは、世界的なBitcoin、Ethereum、そしてLitecoinの取引所です。"
},
"cancel": {
"message": "キャンセル"
},
+ "classicInterface": {
+ "message": "旧インタフェイスを使用"
+ },
"clickCopy": {
"message": "クリックしてコピー"
},
@@ -126,6 +132,9 @@
"message": "暗号通貨",
"description": "Exchange type (cryptocurrencies)"
},
+ "currentConversion": {
+ "message": "基軸通貨"
+ },
"customGas": {
"message": "ガスのカスタマイズ"
},
@@ -135,14 +144,17 @@
"customRPC": {
"message": "カスタムRPC"
},
+ "decimal": {
+ "message": "小数点桁数"
+ },
"defaultNetwork": {
- "message": "Etherトランザクションのデフォルトのネットワークはメインネットです。"
+ "message": "デフォルトのEther送受信ネットワークはメインネットです。"
},
"denExplainer": {
"message": "DENとは、あなたのパスワードが暗号化されたMetaMask内のストレージです。"
},
"deposit": {
- "message": "デポジット"
+ "message": "受取り"
},
"depositBTC": {
"message": "あなたのBTCを次のアドレスへデポジット:"
@@ -161,13 +173,13 @@
"message": "法定通貨でデポジット"
},
"depositFromAccount": {
- "message": "別のアカウントからデポジット"
+ "message": "別のアカウントから入金"
},
"depositShapeShift": {
- "message": "ShapeShiftでデポジット"
+ "message": "ShapeShiftで入金"
},
"depositShapeShiftExplainer": {
- "message": "あなたが他の暗号通貨を持っているなら、Etherにトレードしてダイレクトにメタマスクウォレットへのデポジットが可能です。アカウント作成は不要。"
+ "message": "他の暗号通貨をEtherと交換してMetaMaskのウォレットへ入金できます。アカウント作成は不要です。"
},
"details": {
"message": "詳細"
@@ -176,10 +188,10 @@
"message": "ダイレクトデポジット"
},
"directDepositEther": {
- "message": "Etherをダイレクトデポジット"
+ "message": "Etherを直接受け取り"
},
"directDepositEtherExplainer": {
- "message": "あなたがEtherをすでにお持ちなら、ダイレクトデポジットは新しいウォレットにEtherを入手する最も迅速な方法です。"
+ "message": "Etherをすでにお持ちなら、MetaMaskの新しいウォレットにEtherを送信することができます。"
},
"done": {
"message": "完了"
@@ -197,7 +209,7 @@
"message": "パスワードを入力"
},
"etherscanView": {
- "message": "Etherscanでアカウントを見る"
+ "message": "Etherscanでアカウントを参照"
},
"exchangeRate": {
"message": "交換レート"
@@ -257,7 +269,7 @@
"message": "Etherをゲット"
},
"getEtherFromFaucet": {
- "message": "フォーセットで $1のEtherをゲット",
+ "message": "フォーセットで $1のEtherを得ることができます。",
"description": "Displays network name for Ether faucet"
},
"greaterThanMin": {
@@ -281,12 +293,15 @@
"message": "どのようにEtherをデポジットしますか?"
},
"import": {
- "message": "インポート",
+ "message": "追加",
"description": "Button to import an account from a selected file"
},
"importAccount": {
"message": "アカウントのインポート"
},
+ "importAccountMsg": {
+ "message":"追加したアカウントはMetaMaskのアカウントシードフレーズとは関連付けられません。インポートしたアカウントについての詳細は"
+ },
"importAnAccount": {
"message": "アカウントをインポート"
},
@@ -298,7 +313,10 @@
"description": "status showing that an account has been fully loaded into the keyring"
},
"infoHelp": {
- "message": "インフォメーションとヘルプ"
+ "message": "情報とヘルプ"
+ },
+ "insufficientFunds": {
+ "message": "残高不足"
},
"invalidAddress": {
"message": "アドレスが無効です。"
@@ -354,7 +372,7 @@
"message": "マイアカウント"
},
"needEtherInWallet": {
- "message": "MetaMaskを使って分散型アプリケーションと対話するためには、あなたのウォレットにEtherが必要になります。"
+ "message": "MetaMaskを使って分散型アプリケーションを使用するためには、このウォレットにEtherが必要です。"
},
"needImportFile": {
"message": "インポートするファイルを選択してください。",
@@ -383,6 +401,9 @@
"newRecipient": {
"message": "新規受取人"
},
+ "newRPC": {
+ "message": "新しいRPCのURLを追加"
+ },
"next": {
"message": "次へ"
},
@@ -460,12 +481,21 @@
"rejected": {
"message": "拒否されました"
},
+ "resetAccount": {
+ "message": "アカウントをリセット"
+ },
+ "restoreFromSeed": {
+ "message": "パスフレーズから復元する"
+ },
"required": {
"message": "必要です。"
},
"retryWithMoreGas": {
"message": "より高いガスプライスで再度試して下さい。"
},
+ "revealSeedWords": {
+ "message": "パスフレーズを表示"
+ },
"revert": {
"message": "元に戻す"
},
@@ -495,8 +525,11 @@
"sendTokens": {
"message": "トークンを送る"
},
+ "onlySendToEtherAddress": {
+ "message": "ETHはイーサリウムアカウントのみに送信できます。"
+ },
"sendTokensAnywhere": {
- "message": "イーサリアムのアカウントを持っている人にトークンを送る"
+ "message": "イーサリアムアカウントを持っている人にトークンを送る"
},
"settings": {
"message": "設定"
@@ -544,9 +577,21 @@
"message": "ShapeShiftで $1をETHにする",
"description": "system will fill in deposit type in start of message"
},
+ "tokenAddress": {
+ "message": "トークンアドレス"
+ },
"tokenBalance": {
"message": "あなたのトークン残高:"
},
+ "tokenSelection": {
+ "message": "トークンを検索、またはリストから選択してください。"
+ },
+ "tokenSymbol": {
+ "message": "トークンシンボル"
+ },
+ "tokenWarning1": {
+ "message": "MetaMaskのアカウントで取得したアカウントのみ追加できます。他のアカウントを使用して取得したトークンは、カスタムトークンを使用してください。"
+ },
"total": {
"message": "合計"
},
@@ -591,6 +636,9 @@
"usedByClients": {
"message": "様々なクライアントによって使用されています。"
},
+ "useOldUI": {
+ "message": "旧UIに切り替え"
+ },
"viewAccount": {
"message": "アカウントを見る"
},
diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json
index c9eb178f9..e770392d0 100644
--- a/app/_locales/pt/messages.json
+++ b/app/_locales/pt/messages.json
@@ -223,7 +223,7 @@
"done": {
"message": "Finalizado"
},
- "downloadStatelogs": {
+ "downloadStateLogs": {
"message": "Descarregar Registos de Estado"
},
"edit": {
diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json
new file mode 100644
index 000000000..0532f11b2
--- /dev/null
+++ b/app/_locales/sl/messages.json
@@ -0,0 +1,819 @@
+{
+ "accept": {
+ "message": "Sprejmi"
+ },
+ "account": {
+ "message": "Račun"
+ },
+ "accountDetails": {
+ "message": "Podrobnosti računa"
+ },
+ "accountName": {
+ "message": "Ime računa"
+ },
+ "address": {
+ "message": "Naslov"
+ },
+ "addCustomToken": {
+ "message": "Dodaj žeton po meri"
+ },
+ "addToken": {
+ "message": "Dodaj žeton"
+ },
+ "addTokens": {
+ "message": "Dodaj žetone"
+ },
+ "amount": {
+ "message": "Znesek"
+ },
+ "amountPlusGas": {
+ "message": "Znesek + Gas"
+ },
+ "appDescription": {
+ "message": "Denarnica za Ethereum v brskalniku",
+ "description": "The description of the application"
+ },
+ "appName": {
+ "message": "MetaMask",
+ "description": "The name of the application"
+ },
+ "attemptingConnect": {
+ "message": "Povezovanje z verigo blokov ..."
+ },
+ "attributions": {
+ "message": "Dodelitve"
+ },
+ "available": {
+ "message": "Na voljo"
+ },
+ "back": {
+ "message": "Nazaj"
+ },
+ "balance": {
+ "message": "Znesek:"
+ },
+ "balances": {
+ "message": "Vaš znesek"
+ },
+ "balanceIsInsufficientGas": {
+ "message": "Napačen znesek za skupno gas vrednost"
+ },
+ "beta": {
+ "message": "BETA"
+ },
+ "betweenMinAndMax": {
+ "message": "mora biti večji ali enak $1 in manjši ali enak $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "blockiesIdenticon": {
+ "message": "Uporabite Blockies Identicon"
+ },
+ "borrowDharma": {
+ "message": "Izposoja z Dharma (Beta)"
+ },
+ "builtInCalifornia": {
+ "message": "MetaMask je ustvarjen v Kaliforniji."
+ },
+ "buy": {
+ "message": "Kupi"
+ },
+ "buyCoinbase": {
+ "message": "Kupi na Coinbase"
+ },
+ "buyCoinbaseExplainer": {
+ "message": "Coinbase je najpopularnejši načun za kupovanje in prodajo bitcoinov, ethereuma, in litecoina."
+ },
+ "cancel": {
+ "message": "Prekliči"
+ },
+ "classicInterface": {
+ "message": "Uporabi navaden način"
+ },
+ "clickCopy": {
+ "message": "Kliknite za kopiranje"
+ },
+ "confirm": {
+ "message": "Potrdi"
+ },
+ "confirmContract": {
+ "message": "Potrdi pogodbo"
+ },
+ "confirmPassword": {
+ "message": "Potrdi geslo"
+ },
+ "confirmTransaction": {
+ "message": "Potrdi transakcijo"
+ },
+ "continue": {
+ "message": "Nadaljuj"
+ },
+ "continueToCoinbase": {
+ "message": "Nadaljuj na Coinbase"
+ },
+ "contractDeployment": {
+ "message": "Ustvarjanje pogodbe"
+ },
+ "conversionProgress": {
+ "message": "Poteka pretvorba"
+ },
+ "copiedButton": {
+ "message": "Kopirano"
+ },
+ "copiedClipboard": {
+ "message": "Kopirano v odložišče"
+ },
+ "copiedExclamation": {
+ "message": "Kopirano!"
+ },
+ "copiedSafe": {
+ "message": "Prilepil sem ga na varno!"
+ },
+ "copy": {
+ "message": "Kopiraj"
+ },
+ "copyToClipboard": {
+ "message": "Kopiraj v odložišče"
+ },
+ "copyButton": {
+ "message": " Kopiraj "
+ },
+ "copyPrivateKey": {
+ "message": "To je vaš zesebni ključ (kliknite za kopiranje)"
+ },
+ "create": {
+ "message": "Ustvari"
+ },
+ "createAccount": {
+ "message": "Ustvari račun"
+ },
+ "createDen": {
+ "message": "Ustvari"
+ },
+ "crypto": {
+ "message": "Kripto",
+ "description": "Exchange type (cryptocurrencies)"
+ },
+ "currentConversion": {
+ "message": "Trenutna cena"
+ },
+ "currentNetwork": {
+ "message": "Trenutno omrežje"
+ },
+ "customGas": {
+ "message": "Prilagodi gas"
+ },
+ "customize": {
+ "message": "Prilagodi"
+ },
+ "customRPC": {
+ "message": "Poljuben RPC"
+ },
+ "decimalsMustZerotoTen": {
+ "message": "Decimalk mora biti vsaj 0, in ne več kot 36."
+ },
+ "decimal": {
+ "message": "Decimalke natančnosti"
+ },
+ "defaultNetwork": {
+ "message": "Privzeto omrežje za transakcije je Main Net."
+ },
+ "denExplainer": {
+ "message": "DEN je vaša šifrirana shramba v MetaMasku."
+ },
+ "deposit": {
+ "message": "Vplačilo"
+ },
+ "depositBTC": {
+ "message": "Vplačajte vaš BTC na spodnji naslov:"
+ },
+ "depositCoin": {
+ "message": "Vplačajte $1 na spodnji naslov",
+ "description": "Tells the user what coin they have selected to deposit with shapeshift"
+ },
+ "depositEth": {
+ "message": "Vplačilo ETH"
+ },
+ "depositEther": {
+ "message": "Vplačilo ethera"
+ },
+ "depositFiat": {
+ "message": "Vplačilo s klasičnimi valutami"
+ },
+ "depositFromAccount": {
+ "message": "Vplačilo iz drugega računa"
+ },
+ "depositShapeShift": {
+ "message": "Vplačilo z ShapeShift"
+ },
+ "depositShapeShiftExplainer": {
+ "message": "Če imate druge kriptovalute, lahko vpačate ether neposredno v MetaMask. Brez računov."
+ },
+ "details": {
+ "message": "Podrobnosti"
+ },
+ "directDeposit": {
+ "message": "Direktno vplačilo"
+ },
+ "directDepositEther": {
+ "message": "Direktno vplačilo ehera"
+ },
+ "directDepositEtherExplainer": {
+ "message": "Če že imate ether, ga lahko najhitreje dobite v MetaMask z direktnim vplačilom."
+ },
+ "done": {
+ "message": "Končano"
+ },
+ "downloadStatelogs": {
+ "message": "Prenesi state dnevnike"
+ },
+ "edit": {
+ "message": "Uredi"
+ },
+ "editAccountName": {
+ "message": "Uredi ime računa"
+ },
+ "emailUs": {
+ "message": "Pišite nam!"
+ },
+ "encryptNewDen": {
+ "message": "Šifrirajte DEN"
+ },
+ "enterPassword": {
+ "message": "Vpišite geslo"
+ },
+ "enterPasswordConfirm": {
+ "message": "Potrdite geslo"
+ },
+ "etherscanView": {
+ "message": "Poglejte račun na Etherscan"
+ },
+ "exchangeRate": {
+ "message": "Menjalni tečaj"
+ },
+ "exportPrivateKey": {
+ "message": "Izvozi zasebni ključ"
+ },
+ "exportPrivateKeyWarning": {
+ "message": "Izvažanje zasebnih ključev je na lastno odgovornost."
+ },
+ "failed": {
+ "message": "Ni uspelo"
+ },
+ "fiat": {
+ "message": "FIAT",
+ "description": "Exchange type"
+ },
+ "fileImportFail": {
+ "message": "Uvoz z datoteko ni uspel? Kliknite tukaj!",
+ "description": "Helps user import their account from a JSON file"
+ },
+ "followTwitter": {
+ "message": "Sledite nam na Twitterju"
+ },
+ "from": {
+ "message": "Od"
+ },
+ "fromToSame": {
+ "message": "From and To address cannot be the same"
+ },
+ "fromShapeShift": {
+ "message": "Od ShapeShift"
+ },
+ "gas": {
+ "message": "Gas",
+ "description": "Short indication of gas cost"
+ },
+ "gasFee": {
+ "message": "Gas fee"
+ },
+ "gasLimit": {
+ "message": "Gas limit"
+ },
+ "gasLimitCalculation": {
+ "message": "Priporočen gas limit je izračunan glede na omrežje."
+ },
+ "gasLimitRequired": {
+ "message": "Gas limit je zahtevan"
+ },
+ "gasLimitTooLow": {
+ "message": "Gas limit mora biti najmanj 21000"
+ },
+ "generatingSeed": {
+ "message": "Ustvarjenje seed ..."
+ },
+ "gasPrice": {
+ "message": "Gas price (GWEI)"
+ },
+ "gasPriceCalculation": {
+ "message": "Priporočen gas price je izračunan glede na omrežje"
+ },
+ "gasPriceRequired": {
+ "message": "Gas price je zahtevan"
+ },
+ "getEther": {
+ "message": "Pridobite ether"
+ },
+ "getEtherFromFaucet": {
+ "message": "Pridobite ether iz fauceta za $1",
+ "description": "Displays network name for Ether faucet"
+ },
+ "greaterThanMin": {
+ "message": "mora biti višji ali enak $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "here": {
+ "message": "tukaj",
+ "description": "as in -click here- for more information (goes with troubleTokenBalances)"
+ },
+ "hereList": {
+ "message": "Tukaj je seznam!!!"
+ },
+ "hide": {
+ "message": "Skrij"
+ },
+ "hideToken": {
+ "message": "Skrij žeton"
+ },
+ "hideTokenPrompt": {
+ "message": "Skrijem žeton?"
+ },
+ "howToDeposit": {
+ "message": "Kako želite vplačati ether?"
+ },
+ "holdEther": {
+ "message": "Omogoča vam, da imate eter in žetone in služi kot most za decentralizirane aplikacije."
+ },
+ "import": {
+ "message": "Uvozi",
+ "description": "Button to import an account from a selected file"
+ },
+ "importAccount": {
+ "message": "Uvozi račun"
+ },
+ "importAccountMsg": {
+ "message":" Uvoženi računi ne bodo povezani s prvotnim seedphaseom. Preberite več o uvoženih računih "
+ },
+ "importAnAccount": {
+ "message": "Uvozi račun"
+ },
+ "importDen": {
+ "message": "Uvozi DEN"
+ },
+ "imported": {
+ "message": "Uvoženo",
+ "description": "status showing that an account has been fully loaded into the keyring"
+ },
+ "infoHelp": {
+ "message": "Info & Pomoč"
+ },
+ "insufficientFunds": {
+ "message": "Nezadostna sredstva."
+ },
+ "insufficientTokens": {
+ "message": "Nezadostni žetoni."
+ },
+ "invalidAddress": {
+ "message": "Nepravilen naslov"
+ },
+ "invalidAddressRecipient": {
+ "message": "Prejemnikov naslov je neveljaven"
+ },
+ "invalidGasParams": {
+ "message": "Nepravilno nastavljen gas"
+ },
+ "invalidInput": {
+ "message": "Napačen vnos."
+ },
+ "invalidRequest": {
+ "message": "Napačna zahteva"
+ },
+ "invalidRPC": {
+ "message": "Napačen RPC URI"
+ },
+ "jsonFail": {
+ "message": "Nekaj je bilo narobe. Prepričajte se, da je JSON datoteka pravilno oblikovana."
+ },
+ "jsonFile": {
+ "message": "JSON datoteka",
+ "description": "format for importing an account"
+ },
+ "kovan": {
+ "message": "Testno omrežje Kovan"
+ },
+ "knowledgeDataBase": {
+ "message": "Obiščite našo pomoč"
+ },
+ "lessThanMax": {
+ "message": "mora biti večji ali enak $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "likeToAddTokens": {
+ "message": "Želite dodati te žetone?"
+ },
+ "limit": {
+ "message": "Omejitev"
+ },
+ "loading": {
+ "message": "Nalaganje ..."
+ },
+ "loadingTokens": {
+ "message": "Nalaganje žetonov ..."
+ },
+ "localhost": {
+ "message": "Localhost 8545"
+ },
+ "login": {
+ "message": "Prijava"
+ },
+ "logout": {
+ "message": "Odjava"
+ },
+ "loose": {
+ "message": "Loose"
+ },
+ "loweCaseWords": {
+ "message": "seed words imajo lahko le male črke"
+ },
+ "mainnet": {
+ "message": "Glavno omrežje"
+ },
+ "message": {
+ "message": "Sporočilo"
+ },
+ "metamaskDescription": {
+ "message": "MetaMask je varen identitetni sklad za Ethereum."
+ },
+ "min": {
+ "message": "Najmanj"
+ },
+ "myAccounts": {
+ "message": "Moji računi"
+ },
+ "mustSelectOne": {
+ "message": "Izbran mora biti vsaj 1 žeton."
+ },
+ "needEtherInWallet": {
+ "message": "Za interakcijo z decentraliziranimi aplikacijami, ki uporabljajo MetaMask, boste v svoji denarnici potrebovali eter."
+ },
+ "needImportFile": {
+ "message": "Za uvoz morate izbrati datoteko.",
+ "description": "User is important an account and needs to add a file to continue"
+ },
+ "needImportPassword": {
+ "message": "Za izbrano datoteko morate vnesti geslo.",
+ "description": "Password and file needed to import an account"
+ },
+ "negativeETH": {
+ "message": "Ni mogoče poslati negativne vsote ETH."
+ },
+ "networks": {
+ "message": "Omrežja"
+ },
+ "newAccount": {
+ "message": "Nov račun"
+ },
+ "newAccountNumberName": {
+ "message": "Račun $1",
+ "description": "Default name of next account to be created on create account screen"
+ },
+ "newContract": {
+ "message": "Nova pogodba"
+ },
+ "newPassword": {
+ "message": "Novo geslo (min. 8. črk)"
+ },
+ "newRecipient": {
+ "message": "Nov prejemnik"
+ },
+ "newRPC": {
+ "message": "Nov RPC URL"
+ },
+ "next": {
+ "message": "Naprej"
+ },
+ "noAddressForName": {
+ "message": "Za to ime ni bil nastavljen noben naslov."
+ },
+ "noDeposits": {
+ "message": "Ni prejetih vplačil"
+ },
+ "noTransactionHistory": {
+ "message": "Ni zgodovine transakcij."
+ },
+ "noTransactions": {
+ "message": "Ni transakcij"
+ },
+ "notStarted": {
+ "message": "Ni se začelo"
+ },
+ "oldUI": {
+ "message": "Starejši uporabniški vmesnik"
+ },
+ "oldUIMessage": {
+ "message": "Vrnili ste se v starejši uporabniški vmesnik. V novega se lahko vrnete z možnostjo v spustnem meniju v zgornjem desnem kotu."
+ },
+ "or": {
+ "message": "ali",
+ "description": "choice between creating or importing a new account"
+ },
+ "passwordCorrect": {
+ "message": "Prepričajte se, da je geslo pravilno."
+ },
+ "passwordMismatch": {
+ "message": "gesli se ne ujemata",
+ "description": "in password creation process, the two new password fields did not match"
+ },
+ "passwordShort": {
+ "message": "geslo ni dovolj dolgo",
+ "description": "in password creation process, the password is not long enough to be secure"
+ },
+ "pastePrivateKey": {
+ "message": "Tukaj prilepite zasebni ključ:",
+ "description": "For importing an account from a private key"
+ },
+ "pasteSeed": {
+ "message": "Tukaj prilepite seed phrase!"
+ },
+ "personalAddressDetected": {
+ "message": "Osebni naslov je zaznan. Vnesite naslov žetona."
+ },
+ "pleaseReviewTransaction": {
+ "message": "Preglejte transakcijo."
+ },
+ "privacyMsg": {
+ "message": "Politika zasebnosti"
+ },
+ "privateKey": {
+ "message": "Zasebni ključ",
+ "description": "select this type of file to use to import an account"
+ },
+ "privateKeyWarning": {
+ "message": "Opozorilo: Nikoli ne razkrijte tega ključa. Vsakdo s svojimi zasebnimi ključi lahko ukrade vse premoženje v računu."
+ },
+ "privateNetwork": {
+ "message": "Zasebno omrežje"
+ },
+ "qrCode": {
+ "message": "Prikaži QR kodo"
+ },
+ "readdToken": {
+ "message": "Ta žeton lahko dodate tudi v prihodnosti, tako da odprete možnost »Dodaj žeton« v meniju z računi."
+ },
+ "readMore": {
+ "message": "Preberite več."
+ },
+ "readMore2": {
+ "message": "Preberite več."
+ },
+ "receive": {
+ "message": "Prejmite"
+ },
+ "recipientAddress": {
+ "message": "Prejemnikov naslov"
+ },
+ "refundAddress": {
+ "message": "Vaš naslov za vračilo"
+ },
+ "rejected": {
+ "message": "Zavrnjeno"
+ },
+ "resetAccount": {
+ "message": "Ponastavi račun"
+ },
+ "restoreFromSeed": {
+ "message": "Obnovi iz seed phrase"
+ },
+ "required": {
+ "message": "Zahtevano"
+ },
+ "retryWithMoreGas": {
+ "message": "Poskusi z višjim gas price"
+ },
+ "revealSeedWords": {
+ "message": "Prikaži seed words"
+ },
+ "revealSeedWordsWarning": {
+ "message": "Ne obnovite seed words na javnem mestu! Te besede se lahko uporabijo za krajo vseh vaših računov."
+ },
+ "revert": {
+ "message": "Povrni"
+ },
+ "rinkeby": {
+ "message": "Testno omrežje Rinkeby"
+ },
+ "ropsten": {
+ "message": "Testno omrežje Ropsten"
+ },
+ "sampleAccountName": {
+ "message": "npr. Moj nov račun",
+ "description": "Help user understand concept of adding a human-readable name to their account"
+ },
+ "save": {
+ "message": "Shrani"
+ },
+ "saveAsFile": {
+ "message": "Shrani kot datoteko",
+ "description": "Account export process"
+ },
+ "saveSeedAsFile": {
+ "message": "Shrani seed words kot datoteko"
+ },
+ "search": {
+ "message": "Iskanje"
+ },
+ "secretPhrase": {
+ "message": "Tukaj vnesite svoje seed words, da obnovite svoje račune."
+ },
+ "seedPhraseReq": {
+ "message": "seed phrases so dolgi 12 besed"
+ },
+ "select": {
+ "message": "Izberi"
+ },
+ "selectCurrency": {
+ "message": "Izberi valuto"
+ },
+ "selectService": {
+ "message": "Izberi storitev"
+ },
+ "selectType": {
+ "message": "Izberi vrsto"
+ },
+ "send": {
+ "message": "Pošlji"
+ },
+ "sendETH": {
+ "message": "Pošlji ETH"
+ },
+ "sendTokens": {
+ "message": "Pošlji žetone"
+ },
+ "sendTokensAnywhere": {
+ "message": "Pošljite žetone vsem, ki imajo Ethereum račun"
+ },
+ "settings": {
+ "message": "Nastavitve"
+ },
+ "shapeshiftBuy": {
+ "message": "Kupite z Shapeshift"
+ },
+ "showPrivateKeys": {
+ "message": "Prikaži zasebne ključe"
+ },
+ "showQRCode": {
+ "message": "Prikaži QR kodo"
+ },
+ "sign": {
+ "message": "Podpiši"
+ },
+ "signMessage": {
+ "message": "Podpiši sporočilo"
+ },
+ "signNotice": {
+ "message": "To podpisovanje lahko povzroči \nnevarne stranske učinke. Podpisujte samo sporočila \nstrani, ki jim zaupate s svojim celotnim računom.\n Ta nevarna funkcija bo odstranjena v prihodnji različici. "
+ },
+ "sigRequest": {
+ "message": "Zahteva za podpis"
+ },
+ "sigRequested": {
+ "message": "Podpis je zahtevan"
+ },
+ "spaceBetween": {
+ "message": "med besedami je lahko samo presledek"
+ },
+ "status": {
+ "message": "Status"
+ },
+ "stateLogs": {
+ "message": "State dnevniki"
+ },
+ "stateLogsDescription": {
+ "message": "State dnevniki vsebujejo naslove vašega računa in poslane transakcije.."
+ },
+ "submit": {
+ "message": "Potrdi"
+ },
+ "supportCenter": {
+ "message": "Obiščite našo podporo"
+ },
+ "symbolBetweenZeroTen": {
+ "message": "Simbol mora biti dolg od 0 do 10 znakov."
+ },
+ "takesTooLong": {
+ "message": "Traja predolgo?"
+ },
+ "terms": {
+ "message": "Pogoji uporabe"
+ },
+ "testFaucet": {
+ "message": "Testni faucet"
+ },
+ "to": {
+ "message": "Za"
+ },
+ "toETHviaShapeShift": {
+ "message": "$1 v ETH prek ShapeShift",
+ "description": "system will fill in deposit type in start of message"
+ },
+ "tokenAddress": {
+ "message": "Naslov žetona"
+ },
+ "tokenAlreadyAdded": {
+ "message": "Žeton je že bil dodan."
+ },
+ "tokenBalance": {
+ "message": "Vaš znesek žetona:"
+ },
+ "tokenSelection": {
+ "message": "Poiščite žetone ali jih izberite z našega seznama priljubljenih žetonov."
+ },
+ "tokenSymbol": {
+ "message": "Simbol žetona"
+ },
+ "tokenWarning1": {
+ "message": "Spremljajte žetone, ki ste jih kupili s svojim MetaMask računom. Če ste kupili žetone z drugačnim računom, ti žetoni ne bodo prikazani tukaj."
+ },
+ "total": {
+ "message": "Skupno"
+ },
+ "transactions": {
+ "message": "transakcije"
+ },
+ "transactionMemo": {
+ "message": "Opis transakcije (ni zahtevano)"
+ },
+ "transactionNumber": {
+ "message": "Številka transakcije"
+ },
+ "transfers": {
+ "message": "Prenosi"
+ },
+ "troubleTokenBalances": {
+ "message": "Imeli smo težave pri nalaganju vaših žetonov. Ogledate si jih lahko ",
+ "description": "Followed by a link (here) to view token balances"
+ },
+ "twelveWords": {
+ "message": "Edini način za obnovitev MetaMask računa, je teh 12 besed.\nShranite jih na varno in skrivno mesto."
+ },
+ "typePassword": {
+ "message": "Vpišite vaše geslo"
+ },
+ "uiWelcome": {
+ "message": "Dobrodošli v novem uporabniškem vmesniku (Beta)"
+ },
+ "uiWelcomeMessage": {
+ "message": "Zdaj uporabljate novi MetaMask uporabniški vmesnik. Razglejte se, preizkusite nove funkcije, kot so pošiljanje žetonov, in nas obvestite, če imate kakšne težave."
+ },
+ "unavailable": {
+ "message": "Ni na voljo"
+ },
+ "unknown": {
+ "message": "Neznano"
+ },
+ "unknownNetwork": {
+ "message": "Neznano zasebno omrežje"
+ },
+ "unknownNetworkId": {
+ "message": "Neznan ID omrežja"
+ },
+ "uriErrorMsg": {
+ "message": "URI-ji zahtevajo ustrezno HTTP/HTTPS predpono."
+ },
+ "usaOnly": {
+ "message": "Samo za ZDA",
+ "description": "Using this exchange is limited to people inside the USA"
+ },
+ "usedByClients": {
+ "message": "Uporablja jih več različnih odjemalcev"
+ },
+ "useOldUI": {
+ "message": "Uporabi star uporabniški vmesnik"
+ },
+ "validFileImport": {
+ "message": "Za uvoz morate izbrati pravilno datoteko."
+ },
+ "vaultCreated": {
+ "message": "Račun je ustvarjen"
+ },
+ "viewAccount": {
+ "message": "Poglej račun"
+ },
+ "visitWebSite": {
+ "message": "Obiščite našo spletno stran"
+ },
+ "warning": {
+ "message": "Opozorilo"
+ },
+ "welcomeBeta": {
+ "message": "Dobrodošli v MetaMask Beta"
+ },
+ "whatsThis": {
+ "message": "Kaj je to?"
+ },
+ "yourSigRequested": {
+ "message": "Vaš podpis je bil zahtevan"
+ },
+ "youSign": {
+ "message": "Podpisani ste"
+ }
+}
diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json
new file mode 100644
index 000000000..887714f3f
--- /dev/null
+++ b/app/_locales/th/messages.json
@@ -0,0 +1,819 @@
+{
+ "accept": {
+ "message": "ยอมรับ"
+ },
+ "account": {
+ "message": "บัญชี"
+ },
+ "accountDetails": {
+ "message": "รายละเอียดบัญชี"
+ },
+ "accountName": {
+ "message": "ชื่อบัญชี"
+ },
+ "address": {
+ "message": "แอดเดรส"
+ },
+ "addCustomToken": {
+ "message": "เพิ่มโทเค็นด้วยตัวเอง"
+ },
+ "addToken": {
+ "message": "เพิ่มโทเค็น"
+ },
+ "addTokens": {
+ "message": "เพิ่มหลายโทเค็น"
+ },
+ "amount": {
+ "message": "จำนวน"
+ },
+ "amountPlusGas": {
+ "message": "จำนวน + แก๊ส"
+ },
+ "appDescription": {
+ "message": "ส่วนขยายเบราว์เซอร์สำหรับอีเธอเรียม",
+ "description": "The description of the application"
+ },
+ "appName": {
+ "message": "MetaMask",
+ "description": "The name of the application"
+ },
+ "attemptingConnect": {
+ "message": "กำลังเชื่อมต่อกับบล็อกเชน"
+ },
+ "attributions": {
+ "message": "อ้างถึง"
+ },
+ "available": {
+ "message": "ว่าง"
+ },
+ "back": {
+ "message": "กลับ"
+ },
+ "balance": {
+ "message": "ยอดคงเหลือ:"
+ },
+ "balances": {
+ "message": "ยอดคงเหลือของคุณ"
+ },
+ "balanceIsInsufficientGas": {
+ "message": "ยอดคงเหลือไม่พอสำหรับจ่ายค่าแก๊สทั้งหมด"
+ },
+ "beta": {
+ "message": "เบต้า"
+ },
+ "betweenMinAndMax": {
+ "message": "ต้องมากกว่าหรือเท่ากับ $1 และน้อยกว่าหรือเท่ากับ $2",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "blockiesIdenticon": {
+ "message": "ใช้งาน Blockies Identicon"
+ },
+ "borrowDharma": {
+ "message": "ยืมด้วย Dharma (เบต้า)"
+ },
+ "builtInCalifornia": {
+ "message": "MetaMask ออกแบบและพัฒนาที่แคลิฟอร์เนีย"
+ },
+ "buy": {
+ "message": "ซื้อ"
+ },
+ "buyCoinbase": {
+ "message": "ซื้อด้วย Coinbase"
+ },
+ "buyCoinbaseExplainer": {
+ "message": "Coinbase เป็นแหล่งซื้อขายบิตคอยน์ไลท์คอยน์และอีเธอเรียมที่ได้รับความนิยมสูงสุดในโลก"
+ },
+ "cancel": {
+ "message": "ยกเลิก"
+ },
+ "classicInterface": {
+ "message": "ใช้หน้าตาแบบเก่า"
+ },
+ "clickCopy": {
+ "message": "กดเพื่อคัดลอก"
+ },
+ "confirm": {
+ "message": "ยืนยัน"
+ },
+ "confirmContract": {
+ "message": "ยืนยันสัญญา"
+ },
+ "confirmPassword": {
+ "message": "ยืนยันรหัสผ่าน"
+ },
+ "confirmTransaction": {
+ "message": "ยืนยันการทำรายการธุรกรรม"
+ },
+ "continue": {
+ "message": "ทำต่อไป"
+ },
+ "continueToCoinbase": {
+ "message": "ไปที่ Coinbase"
+ },
+ "contractDeployment": {
+ "message": "การติดตั้งสัญญา"
+ },
+ "conversionProgress": {
+ "message": "กำลังดำเนินการแปลงหน่วย"
+ },
+ "copiedButton": {
+ "message": "คัดลอกแล้ว"
+ },
+ "copiedClipboard": {
+ "message": "คัดลอกไปที่คลิบบอร์ดแล้ว"
+ },
+ "copiedExclamation": {
+ "message": "คัดลอกแล้ว!"
+ },
+ "copiedSafe": {
+ "message": "ฉันได้คัดลอกเก็บไว้ในที่ปลอดภัยเรียบร้อยแล้ว"
+ },
+ "copy": {
+ "message": "คัดลอก"
+ },
+ "copyToClipboard": {
+ "message": "คัดลอกไปคลิปบอร์ด"
+ },
+ "copyButton": {
+ "message": " คัดลอก "
+ },
+ "copyPrivateKey": {
+ "message": "นี่คือคีย์ส่วนตัวของคุณ(กดเพื่อคัดลอก)"
+ },
+ "create": {
+ "message": "สร้าง"
+ },
+ "createAccount": {
+ "message": "สร้างบัญชี"
+ },
+ "createDen": {
+ "message": "สร้าง"
+ },
+ "crypto": {
+ "message": "คริปโต",
+ "description": "Exchange type (cryptocurrencies)"
+ },
+ "currentConversion": {
+ "message": "อัตราแลกเปลี่ยนปัจจุบัน"
+ },
+ "currentNetwork": {
+ "message": "เครือข่ายปัจจุบัน"
+ },
+ "customGas": {
+ "message": "กำหนดค่าแก็สเอง"
+ },
+ "customize": {
+ "message": "กำหนดค่าเอง"
+ },
+ "customRPC": {
+ "message": "กำหนดค่า RPC เอง"
+ },
+ "decimalsMustZerotoTen": {
+ "message": "จำนวนต้องมากกว่า 0 และไม่เกิน 36"
+ },
+ "decimal": {
+ "message": "ตำแหน่งของทศนิยม"
+ },
+ "defaultNetwork": {
+ "message": "ค่าเริ่มต้นของเครือข่ายสำหรับทำรายการธุรกรรมอีเธอร์คือ Main Net"
+ },
+ "denExplainer": {
+ "message": "DEN ของคุณคือตัวเก็บข้อมูลที่เข้ารหัสไว้ด้วยรหัสผ่านของคุณภายใน MetaMask "
+ },
+ "deposit": {
+ "message": "ฝาก"
+ },
+ "depositBTC": {
+ "message": "ฝากบิตคอยน์ของคุณไปที่แอดเดรสด้านล่างนี้:"
+ },
+ "depositCoin": {
+ "message": "ฝาก $1 ของคุณไปที่แอดเดรสด้านล่างนี้:",
+ "description": "Tells the user what coin they have selected to deposit with shapeshift"
+ },
+ "depositEth": {
+ "message": "การฝากอีเธอร์"
+ },
+ "depositEther": {
+ "message": "การฝากอีเธอร์"
+ },
+ "depositFiat": {
+ "message": "ฝากด้วยเงินตรา"
+ },
+ "depositFromAccount": {
+ "message": "ฝากจากบัญชีอื่น"
+ },
+ "depositShapeShift": {
+ "message": "ฝากด้วย ShapeShift"
+ },
+ "depositShapeShiftExplainer": {
+ "message": "ถ้ามีเงินสกุลอื่นอยู่ก็สามารถแลกเงินและฝากเป็นอีเธอร์ได้โดยตรงเข้ากระเป๋า MetaMask ได้เลยไม่ต้องสมัครบัญชี"
+ },
+ "details": {
+ "message": "รายละเอียด"
+ },
+ "directDeposit": {
+ "message": "ฝากตรง"
+ },
+ "directDepositEther": {
+ "message": "ฝากอีเธอร์โดยตรง"
+ },
+ "directDepositEtherExplainer": {
+ "message": "ถ้าคุณมีอีเธอร์อยู่แล้ววิธีการที่เร็วที่สุดในการเอาเงินเข้ากระเป๋าใหม่ก็คือการโอนตรงๆ"
+ },
+ "done": {
+ "message": "เสร็จสิ้น"
+ },
+ "downloadStatelogs": {
+ "message": "ดาวน์โหลดล็อกสถานะ"
+ },
+ "edit": {
+ "message": "แก้ไข"
+ },
+ "editAccountName": {
+ "message": "แก้ไขชื่อบัญชี"
+ },
+ "emailUs": {
+ "message": "อีเมลหาเรา!"
+ },
+ "encryptNewDen": {
+ "message": "เข้ารหัส DEN ของคุณ"
+ },
+ "enterPassword": {
+ "message": "ใส่รหัสผ่าน"
+ },
+ "enterPasswordConfirm": {
+ "message": "ใส่รหัสผ่านอีกครั้งเพื่อยืนยัน"
+ },
+ "etherscanView": {
+ "message": "ดูบัญชีบน Etherscan"
+ },
+ "exchangeRate": {
+ "message": "อัตราแลกเปลี่ยน"
+ },
+ "exportPrivateKey": {
+ "message": "ส่งออกคีย์ส่วนตัว"
+ },
+ "exportPrivateKeyWarning": {
+ "message": "ส่งออกคีย์ส่วนตัวโดยคุณรับความเสี่ยงเอง"
+ },
+ "failed": {
+ "message": "ล้มเหลว"
+ },
+ "fiat": {
+ "message": "เงินตรา",
+ "description": "Exchange type"
+ },
+ "fileImportFail": {
+ "message": "นำเข้าไฟล์ไม่สำเหร็จ กดที่นี่!",
+ "description": "Helps user import their account from a JSON file"
+ },
+ "followTwitter": {
+ "message": "ติดตามเราบนทวิตเตอร์"
+ },
+ "from": {
+ "message": "จาก"
+ },
+ "fromToSame": {
+ "message": "แอดเดรสที่ส่งกับที่รับจะต้องไม่ไช่อันเดียวกัน"
+ },
+ "fromShapeShift": {
+ "message": "จาก ShapeShift"
+ },
+ "gas": {
+ "message": "แก็ส",
+ "description": "Short indication of gas cost"
+ },
+ "gasFee": {
+ "message": "ค่าแก๊ส"
+ },
+ "gasLimit": {
+ "message": "วงเงินแก็ส"
+ },
+ "gasLimitCalculation": {
+ "message": "เราแนะนำวงเงินแก็สตามความสำเร็จบนเครือข่าย"
+ },
+ "gasLimitRequired": {
+ "message": "ต้องกำหนดวงเงินแก็ส"
+ },
+ "gasLimitTooLow": {
+ "message": "วงเงินแก็สต้องอย่างน้อย 21000"
+ },
+ "generatingSeed": {
+ "message": "กำลังสร้างชีด..."
+ },
+ "gasPrice": {
+ "message": "ราคาแก๊ส (GWEI)"
+ },
+ "gasPriceCalculation": {
+ "message": "เราแนะนำราคาแก็สตามความสำเร็จบนเครือข่าย"
+ },
+ "gasPriceRequired": {
+ "message": "ต้องมีราคาแก๊ส"
+ },
+ "getEther": {
+ "message": "รับอีเธอร์"
+ },
+ "getEtherFromFaucet": {
+ "message": "รับอีเธอร์ที่ปล่อยจาก $1",
+ "description": "Displays network name for Ether faucet"
+ },
+ "greaterThanMin": {
+ "message": "ต้องมากกว่าหรือเท่ากับ $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "here": {
+ "message": "ที่นี่",
+ "description": "as in -click here- for more information (goes with troubleTokenBalances)"
+ },
+ "hereList": {
+ "message": "รายการอยู่ที่นี่!!!!"
+ },
+ "hide": {
+ "message": "ซ่อน"
+ },
+ "hideToken": {
+ "message": "ซ่อนโทเค็น"
+ },
+ "hideTokenPrompt": {
+ "message": "ซ่อนโทเค็นหรือไม่?"
+ },
+ "howToDeposit": {
+ "message": "คุณต้องการฝากอีเธอร์อย่างไร?"
+ },
+ "holdEther": {
+ "message": "ช่วยคุณถืออีเทอร์และโทเค็นและทำหน้าที่เป็นสะพานเชื่อมต่อกับแอพพลิเคชันแบบกระจาย"
+ },
+ "import": {
+ "message": "นำเข้า",
+ "description": "Button to import an account from a selected file"
+ },
+ "importAccount": {
+ "message": "นำเข้าบัญชี"
+ },
+ "importAccountMsg": {
+ "message":"บัญชีที่นำเข้าจะไม่ถูกรวมกับบัญชีที่สร้างด้วยคำเเริ่มต้นบนเมต้ามาร์สในตอนแรก เรียนรู้เพิ่มเติมเกี่ยวกับบัญชีที่นำเข้า"
+ },
+ "importAnAccount": {
+ "message": "นำเข้าบัญชี"
+ },
+ "importDen": {
+ "message": "นำเข้า DEN ที่มีอยู่แล้ว"
+ },
+ "imported": {
+ "message": "นำเข้าเรียบร้อย",
+ "description": "status showing that an account has been fully loaded into the keyring"
+ },
+ "infoHelp": {
+ "message": "ข้อมูลและความช่วยเหลือ"
+ },
+ "insufficientFunds": {
+ "message": "เงินทุนไม่เพียงพอ"
+ },
+ "insufficientTokens": {
+ "message": "โทเค็นไม่เพียงพอ"
+ },
+ "invalidAddress": {
+ "message": "แอดแดรสไม่ถูกต้อง"
+ },
+ "invalidAddressRecipient": {
+ "message": "แอดแดรสผู้รับไม่ถูกต้อง"
+ },
+ "invalidGasParams": {
+ "message": "ตั้งค่าแก๊สไม่ถูกต้อง"
+ },
+ "invalidInput": {
+ "message": "อินพุทไม่ถูกต้อง"
+ },
+ "invalidRequest": {
+ "message": "คำร้องขอไม่ถูกต้อง"
+ },
+ "invalidRPC": {
+ "message": "RPC URI ไม่ถูกต้อง"
+ },
+ "jsonFail": {
+ "message": "เกิดบางอย่างผิดพลาด โปรดตรวจสอบว่าไฟล์ JSON ของคุณมีรูปแบบที่ถูกต้อง."
+ },
+ "jsonFile": {
+ "message": "ไฟล์ JSON",
+ "description": "format for importing an account"
+ },
+ "kovan": {
+ "message": "เครือข่ายทดสอบ Kovan"
+ },
+ "knowledgeDataBase": {
+ "message": "ไปที่คลังความรู้ของเรา"
+ },
+ "lessThanMax": {
+ "message": "ต้องน้อยกว่าหรือเท่ากับ $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "likeToAddTokens": {
+ "message": "คุณต้องการเพิ่มโทเค็นเหล่านี้หรือไม่?"
+ },
+ "limit": {
+ "message": "ข้อจำกัด"
+ },
+ "loading": {
+ "message": "กำลังโหลด..."
+ },
+ "loadingTokens": {
+ "message": "กำลังโหลดโทเค็น..."
+ },
+ "localhost": {
+ "message": "Localhost 8545"
+ },
+ "login": {
+ "message": "เข้าสู่ระบบ"
+ },
+ "logout": {
+ "message": "ออกจากระบบ"
+ },
+ "loose": {
+ "message": "อิสระ"
+ },
+ "loweCaseWords": {
+ "message": "กลุ่มคำชีดมีเพียงตัวพิมพ์เล็กเท่านั้น"
+ },
+ "mainnet": {
+ "message": "เครือข่าย Main Net"
+ },
+ "message": {
+ "message": "ข้อความ"
+ },
+ "metamaskDescription": {
+ "message": "MetaMask คือที่เก็บตัวตนนิรภัยสำหรับอีเธอเรียม"
+ },
+ "min": {
+ "message": "ขั้นต่ำ"
+ },
+ "myAccounts": {
+ "message": "บัญชีของฉัน"
+ },
+ "mustSelectOne": {
+ "message": "ต้องเลือกอย่างน้อย 1 โทเค็น"
+ },
+ "needEtherInWallet": {
+ "message": "คุณจะต้องมีอีเธอร์ในกระเป๋าเงินของคุณในการใช้งานกับแอพพลิเคชันแบบกระจายด้วย MetaMask"
+ },
+ "needImportFile": {
+ "message": "คุณต้องเลือกไฟล์ที่จะนำเข้า",
+ "description": "User is important an account and needs to add a file to continue"
+ },
+ "needImportPassword": {
+ "message": "คุณต้องป้อนรหัสผ่านสำหรับไฟล์ที่เลือก",
+ "description": "Password and file needed to import an account"
+ },
+ "negativeETH": {
+ "message": "ไม่สามารถส่งอีเธอร์เป็นจำนวนติดลบได้"
+ },
+ "networks": {
+ "message": "เครือข่าย"
+ },
+ "newAccount": {
+ "message": "บัญชีใหม่"
+ },
+ "newAccountNumberName": {
+ "message": "บัญชี $1",
+ "description": "Default name of next account to be created on create account screen"
+ },
+ "newContract": {
+ "message": "สร้างสัญญาใหม่"
+ },
+ "newPassword": {
+ "message": "รหัสผ่านใหม่(ขั้นต่ำ 8 ตัวอักษร)"
+ },
+ "newRecipient": {
+ "message": "ผู้รับใหม่"
+ },
+ "newRPC": {
+ "message": "RPC URL ใหม่"
+ },
+ "next": {
+ "message": "ถัดไป"
+ },
+ "noAddressForName": {
+ "message": "ยังไม่มีแอดแดรสไหนตั้งในชื่อนี้"
+ },
+ "noDeposits": {
+ "message": "ไม่มีเงินฝากเข้ามา"
+ },
+ "noTransactionHistory": {
+ "message": "ไม่มีรายการธุรกรรมในอดีต"
+ },
+ "noTransactions": {
+ "message": "ยังไม่มีรายการธุรกรรม"
+ },
+ "notStarted": {
+ "message": "ยังไม่เริ่ม"
+ },
+ "oldUI": {
+ "message": "หน้าตาแบบเก่า"
+ },
+ "oldUIMessage": {
+ "message": "คุณได้เปลี่ยนเป็นหน้าตาแบบเก่าแล้ว คุณสามารถเปลี่ยนเป็นหน้าตาแบบใหม่ได้โดยไปที่ตัวเลือกตรงเมนูมุมขวาบน"
+ },
+ "or": {
+ "message": "หรือ",
+ "description": "choice between creating or importing a new account"
+ },
+ "passwordCorrect": {
+ "message": "โปรดตรวจสอบว่ารหัสผ่านของคุณถูกต้อง"
+ },
+ "passwordMismatch": {
+ "message": "รหัสผ่านไม่ตรงกัน",
+ "description": "in password creation process, the two new password fields did not match"
+ },
+ "passwordShort": {
+ "message": "รหัสผ่านไม่ยาวพอ",
+ "description": "in password creation process, the password is not long enough to be secure"
+ },
+ "pastePrivateKey": {
+ "message": "วางคีย์ส่วนตัวของคุณที่นี่:",
+ "description": "For importing an account from a private key"
+ },
+ "pasteSeed": {
+ "message": "วางคำชีดของคุณที่นี่!"
+ },
+ "personalAddressDetected": {
+ "message": "ตรวจพบแอดแดรสส่วนตัวแล้ว ใส่แอดแดรสสัญญาโทเค็น"
+ },
+ "pleaseReviewTransaction": {
+ "message": "โปรดตรวจสอบธุรกรรมของคุณ"
+ },
+ "privacyMsg": {
+ "message": "นโยบายสความเป็นส่วนตัว"
+ },
+ "privateKey": {
+ "message": "คีย์ส่วนตัว",
+ "description": "select this type of file to use to import an account"
+ },
+ "privateKeyWarning": {
+ "message": "คำเตือน: ห้ามเปิดเผยคีย์นี้ ทุกคนที่มีคีย์ส่วนตัวสามารถขโมยข้อมูลใด ๆ ที่เก็บไว้ในบัญชีของคุณได้"
+ },
+ "privateNetwork": {
+ "message": "เครือข่ายส่วนตัว"
+ },
+ "qrCode": {
+ "message": "แสดง QR Code"
+ },
+ "readdToken": {
+ "message": "คุณสามารถเพิ่มโทเค็นนี้ในอนาคตได้โดยไปที่ “เพิ่มโทเค็น” ในเมนูตัวเลือกบัญชีของคุณ"
+ },
+ "readMore": {
+ "message": "อ่านเพิ่มเติมที่นี่"
+ },
+ "readMore2": {
+ "message": "อ่านเพิ่มเติม"
+ },
+ "receive": {
+ "message": "รับ"
+ },
+ "recipientAddress": {
+ "message": "แอดแดรสผู้รับ"
+ },
+ "refundAddress": {
+ "message": "แอดแดรสสำหรับการคืนเงินของคุณ"
+ },
+ "rejected": {
+ "message": "ถูกปฏิเสธ"
+ },
+ "resetAccount": {
+ "message": "รีเซ็ตบัญชี"
+ },
+ "restoreFromSeed": {
+ "message": "กู้คืนจากกลุ่มคำชีด"
+ },
+ "required": {
+ "message": "จำเป็น"
+ },
+ "retryWithMoreGas": {
+ "message": "ลองใหม่ด้วยราคาแก๊สที่สูงกว่านี้ที่นี่"
+ },
+ "revealSeedWords": {
+ "message": "เปิดเผยกลุ่มคำชีด"
+ },
+ "revealSeedWordsWarning": {
+ "message": "อย่าเปิดเผยคำกลุ่มคำชีดของคุณในที่สาธารณะ! คำเหล่านี้สามารถใช้เพื่อขโมยบัญชีทั้งหมดของคุณ"
+ },
+ "revert": {
+ "message": "ย้อนกลับ"
+ },
+ "rinkeby": {
+ "message": "เครือข่ายทดสอบ Rinkeby"
+ },
+ "ropsten": {
+ "message": "เครือข่ายทดสอบ Ropsten"
+ },
+ "sampleAccountName": {
+ "message": "เช่น บัญชีเฮงเฮงของฉัน",
+ "description": "Help user understand concept of adding a human-readable name to their account"
+ },
+ "save": {
+ "message": "บันทึก"
+ },
+ "saveAsFile": {
+ "message": "บันทึกเป็นไฟล์",
+ "description": "Account export process"
+ },
+ "saveSeedAsFile": {
+ "message": "บันทึกกลุ่มคำชีดเป็นไฟล์"
+ },
+ "search": {
+ "message": "ค้นหา"
+ },
+ "secretPhrase": {
+ "message": "ป้อนกลุ่มคำสิบสองคำเพื่อกู้คืนตู้เซฟของคุณ"
+ },
+ "seedPhraseReq": {
+ "message": "กลุ่มคำชีดมีความยาว 12 คำ"
+ },
+ "select": {
+ "message": "เลือก"
+ },
+ "selectCurrency": {
+ "message": "เลือกสกุลเงิน"
+ },
+ "selectService": {
+ "message": "เลือกบริการ"
+ },
+ "selectType": {
+ "message": "เลือกประเภท"
+ },
+ "send": {
+ "message": "ส่ง"
+ },
+ "sendETH": {
+ "message": "ส่งอีเธอร์"
+ },
+ "sendTokens": {
+ "message": "ส่งโทเค็น"
+ },
+ "sendTokensAnywhere": {
+ "message": "ส่งโทเค็นไปให้ทุกคนที่มีบัญชีอีเธอเรียม"
+ },
+ "settings": {
+ "message": "การตั้งค่า"
+ },
+ "shapeshiftBuy": {
+ "message": "ซื้อด้วย Shapeshift"
+ },
+ "showPrivateKeys": {
+ "message": "แสดงคีย์ส่วนตัว"
+ },
+ "showQRCode": {
+ "message": "แสดง QR Code"
+ },
+ "sign": {
+ "message": "เซ็นชื่อ"
+ },
+ "signMessage": {
+ "message": "เซ็นชื่อในข้อความ"
+ },
+ "signNotice": {
+ "message": "การเซ็นชื่อในข้อความนี้อาจจะเป็นอันตรายได้ \nเซ็นชื่อเฉพาะข้อความจากแหล่งที่คุณไว้วางใจได้จริง ๆ เท่านั้น \nวิธีที่อันตรายนี้จะถูกลบออกในอนาคต"
+ },
+ "sigRequest": {
+ "message": "ขอลายเซ็น"
+ },
+ "sigRequested": {
+ "message": "ขอลายเซ็นแล้ว"
+ },
+ "spaceBetween": {
+ "message": "มีช่องว่างได้เพียงตัวเดียวระหว่างคำเท่านั้น"
+ },
+ "status": {
+ "message": "สถานะ"
+ },
+ "stateLogs": {
+ "message": "บันทึกของสถานะ"
+ },
+ "stateLogsDescription": {
+ "message": "บันทึกของสถานะประกอบด้วยแอดแดรสสาธารณะและธุรกรรมที่ส่ง"
+ },
+ "submit": {
+ "message": "ตกลง"
+ },
+ "supportCenter": {
+ "message": "ไปที่ศูนย์สนับสนุนของเรา"
+ },
+ "symbolBetweenZeroTen": {
+ "message": "สัญลักษณ์ต้องมีความยาวตั้งแต่ 0 ถึง 10 อักขระ"
+ },
+ "takesTooLong": {
+ "message": "ใช้เวลานานเกินไปใช่หรือไม่?"
+ },
+ "terms": {
+ "message": "ข้อตกลงในการใช้งาน"
+ },
+ "testFaucet": {
+ "message": "ตัวแจกจ่ายเพื่อการทดสอบ"
+ },
+ "to": {
+ "message": "ถึง"
+ },
+ "toETHviaShapeShift": {
+ "message": "$1 เป็นอีเธอร์โดย ShapeShift",
+ "description": "system will fill in deposit type in start of message"
+ },
+ "tokenAddress": {
+ "message": "แอดแดรสโทเค็น"
+ },
+ "tokenAlreadyAdded": {
+ "message": "โทเคนได้ถูกเพิ่มไปแล้ว"
+ },
+ "tokenBalance": {
+ "message": "ยอดโทเค็นคงเหลือของคุณคือ:"
+ },
+ "tokenSelection": {
+ "message": "ค้นหาโทเค็นหรือเลือกจากรายการโทเค็นยอดนิยมของเรา"
+ },
+ "tokenSymbol": {
+ "message": "สัญลักษณ์ประจำตัว"
+ },
+ "tokenWarning1": {
+ "message": "ติดตามโทเค็นที่คุณซื้อด้วยบัญชี MetaMask ของคุณ หากคุณซื้อโทเค็นโดยใช้บัญชีอื่นโทเค็นเหล่านั้นจะไม่ปรากฏที่นี่"
+ },
+ "total": {
+ "message": "รวม"
+ },
+ "transactions": {
+ "message": "ธุรกรรม"
+ },
+ "transactionMemo": {
+ "message": "บันทึกช่วยจำของการทำธุรกรรม (ไม่บังคับ)"
+ },
+ "transactionNumber": {
+ "message": "หมายเลขธุรกรรม"
+ },
+ "transfers": {
+ "message": "โอน"
+ },
+ "troubleTokenBalances": {
+ "message": "เรามีปัญหาในการโหลดยอดโทเค็นคงเหลือของคุณ คุณสามารถดูได้ที่นี่",
+ "description": "Followed by a link (here) to view token balances"
+ },
+ "twelveWords": {
+ "message": "กลุ่มคำ 12 คำเหล่านี้เป็นวิธีเดียวที่จะกู้คืนบัญชี MetaMask ของคุณ \n กรุณาเก็บไว้ในที่ปลอดภัยและเก็บเป็นความลับ"
+ },
+ "typePassword": {
+ "message": "พิมพ์รหัสผ่านของคุณ"
+ },
+ "uiWelcome": {
+ "message": "ยินดีต้อนรับสู่หน้าตาใหม่ (เบต้า)"
+ },
+ "uiWelcomeMessage": {
+ "message": "ขณะนี้คุณใช้งาน Metamask หน้าตาใหม่แล้ว ลองใช้ความสามรถใหม่ ๆ เช่นการส่งโทเค็นและหากพบปัญหากรุณาแจ้งให้เราทราบ"
+ },
+ "unavailable": {
+ "message": "ใช้งานไม่ได้"
+ },
+ "unknown": {
+ "message": "ไม่รู้จัก"
+ },
+ "unknownNetwork": {
+ "message": "ไม่รู้จักเครือข่ายส่วนตัว"
+ },
+ "unknownNetworkId": {
+ "message": "ไม่รู้จักหมายเลขเครือข่าย"
+ },
+ "uriErrorMsg": {
+ "message": "URI ต้องมีคำนำหน้าเป็น HTTP หรือ HTTPS"
+ },
+ "usaOnly": {
+ "message": "ในสหรัฐอเมริกาเท่านั้น",
+ "description": "Using this exchange is limited to people inside the USA"
+ },
+ "usedByClients": {
+ "message": "ถูกใช้งานโดยหลายไคลเอนท์"
+ },
+ "useOldUI": {
+ "message": "ใช้หน้าตาเก่า"
+ },
+ "validFileImport": {
+ "message": "คุณต้องเลือกไฟล์ที่ถูกต้องเพื่อนำเข้า"
+ },
+ "vaultCreated": {
+ "message": "สร้างตู้เซฟแล้ว"
+ },
+ "viewAccount": {
+ "message": "ดูบัญชี"
+ },
+ "visitWebSite": {
+ "message": "เยี่ยมชมเว็บไซต์ของเรา"
+ },
+ "warning": {
+ "message": "คำเตือน"
+ },
+ "welcomeBeta": {
+ "message": "ยินดีต้อนรับสู่ MetaMask เบต้า"
+ },
+ "whatsThis": {
+ "message": "นี่คืออะไร?"
+ },
+ "yourSigRequested": {
+ "message": "ลายเซ็นของคุณกำลังได้รับการร้องขอ"
+ },
+ "youSign": {
+ "message": "คุณกำลังเซ็นชื่อ"
+ }
+}
diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json
new file mode 100644
index 000000000..e39793430
--- /dev/null
+++ b/app/_locales/zh_TW/messages.json
@@ -0,0 +1,903 @@
+{
+ "accept": {
+ "message": "接受"
+ },
+ "account": {
+ "message": "帳戶"
+ },
+ "accountDetails": {
+ "message": "帳戶詳情"
+ },
+ "accountName": {
+ "message": "帳戶名稱"
+ },
+ "address": {
+ "message": "帳戶地址"
+ },
+ "addCustomToken": {
+ "message": "加入自訂代幣"
+ },
+ "addToken": {
+ "message": "加入代幣"
+ },
+ "addTokens": {
+ "message": "加入多筆代幣"
+ },
+ "amount": {
+ "message": "數額"
+ },
+ "amountPlusGas": {
+ "message": "數額 + Gas"
+ },
+ "appDescription": {
+ "message": "乙太坊瀏覽器擴充插件",
+ "description": "The description of the application"
+ },
+ "appName": {
+ "message": "MetaMask",
+ "description": "The name of the application"
+ },
+ "approved": {
+ "message": "已同意"
+ },
+ "attemptingConnect": {
+ "message": "正在嘗試連接區塊鏈。"
+ },
+ "attributions": {
+ "message": "來源"
+ },
+ "available": {
+ "message": "可使用"
+ },
+ "back": {
+ "message": "上一頁"
+ },
+ "balance": {
+ "message": "餘額:"
+ },
+ "balances": {
+ "message": "你的餘額:"
+ },
+ "balanceIsInsufficientGas": {
+ "message": "當前餘額不足以支付 Gas"
+ },
+ "beta": {
+ "message": "BETA"
+ },
+ "betweenMinAndMax": {
+ "message": "必須大於等於 $1 並且小於等於 $2 。",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "blockiesIdenticon": {
+ "message": "使用 Blockies Identicon"
+ },
+ "borrowDharma": {
+ "message": "透過 Dharma (Beta) 借用"
+ },
+ "builtInCalifornia": {
+ "message": "MetaMask 是在加州設計製造."
+ },
+ "buy": {
+ "message": "購買"
+ },
+ "buyCoinbase": {
+ "message": "在 Coinbase 上購買"
+ },
+ "buyCoinbaseExplainer": {
+ "message": "Coinbase 是世界上最流行的買賣比特幣,以太幣和萊特幣的交易所。"
+ },
+ "ok": {
+ "message": "Ok"
+ },
+ "cancel": {
+ "message": "取消"
+ },
+ "classicInterface": {
+ "message": "使用舊版界面"
+ },
+ "clickCopy": {
+ "message": "點擊複製"
+ },
+ "confirm": {
+ "message": "確認"
+ },
+ "confirmed": {
+ "message": "已確認"
+ },
+ "confirmContract": {
+ "message": "確認合約"
+ },
+ "confirmPassword": {
+ "message": "確認密碼"
+ },
+ "confirmTransaction": {
+ "message": "確認交易"
+ },
+ "continue": {
+ "message": "繼續"
+ },
+ "continueToCoinbase": {
+ "message": "繼續前往 Coinbase"
+ },
+ "contractDeployment": {
+ "message": "合約部署"
+ },
+ "conversionProgress": {
+ "message": "正在取得匯率"
+ },
+ "copiedButton": {
+ "message": "已複製"
+ },
+ "copiedClipboard": {
+ "message": "已複製到剪貼簿"
+ },
+ "copiedExclamation": {
+ "message": "已複製!"
+ },
+ "copiedSafe": {
+ "message": "我已經複製到某個安全的地方了"
+ },
+ "copy": {
+ "message": "複製"
+ },
+ "copyToClipboard": {
+ "message": "複製到剪貼簿"
+ },
+ "copyButton": {
+ "message": " 複製 "
+ },
+ "copyPrivateKey": {
+ "message": "這是你的私鑰(點擊複製)"
+ },
+ "create": {
+ "message": "建立"
+ },
+ "createAccount": {
+ "message": "建立帳戶"
+ },
+ "createDen": {
+ "message": "建立"
+ },
+ "crypto": {
+ "message": "加密",
+ "description": "Exchange type (cryptocurrencies)"
+ },
+ "currentConversion": {
+ "message": "當前匯率"
+ },
+ "currentNetwork": {
+ "message": "當前網路"
+ },
+ "customGas": {
+ "message": "自訂 Gas"
+ },
+ "customToken": {
+ "message": "自訂代幣"
+ },
+ "customize": {
+ "message": "自訂"
+ },
+ "customRPC": {
+ "message": "自訂 RPC"
+ },
+ "decimalsMustZerotoTen": {
+ "message": "小數點後位數至少為0, 最多為36."
+ },
+ "decimal": {
+ "message": "小數點精度"
+ },
+ "defaultNetwork": {
+ "message": "預設 Ether 交易網路為主網路(Main Net)。"
+ },
+ "denExplainer": {
+ "message": "你的 DEN 是在你的 MetaMask 中的加密密碼儲存庫。"
+ },
+ "deposit": {
+ "message": "存入"
+ },
+ "depositBTC": {
+ "message": "將你的 BTC 存入到下面的地址:"
+ },
+ "depositCoin": {
+ "message": "將你的 $1 存入到下面的地址",
+ "description": "Tells the user what coin they have selected to deposit with shapeshift"
+ },
+ "depositEth": {
+ "message": "存入 Eth"
+ },
+ "depositEther": {
+ "message": "存入 Ether"
+ },
+ "depositFiat": {
+ "message": "從法定貨幣存入"
+ },
+ "depositFromAccount": {
+ "message": "從其他帳戶存入"
+ },
+ "depositShapeShift": {
+ "message": "從 ShapeShift 存入"
+ },
+ "depositShapeShiftExplainer": {
+ "message": "如果你擁有其他加密貨幣,你可以直接交易並存入 Ether 到你的 MetaMask 錢包。不需要開帳戶。"
+ },
+ "details": {
+ "message": "詳情"
+ },
+ "directDeposit": {
+ "message": "直接存入"
+ },
+ "directDepositEther": {
+ "message": "直接存入 Ether"
+ },
+ "directDepositEtherExplainer": {
+ "message": "如果你已經擁有了一些 Ether,使用直接存入功能是讓你的新錢包最快取得 Ether 的方式。"
+ },
+ "done": {
+ "message": "完成"
+ },
+ "downloadStatelogs": {
+ "message": "下載狀態紀錄"
+ },
+ "dropped": {
+ "message": "丟棄"
+ },
+ "edit": {
+ "message": "編輯"
+ },
+ "editAccountName": {
+ "message": "編輯帳戶名稱"
+ },
+ "emailUs": {
+ "message": "寄 Email 給我們!"
+ },
+ "encryptNewDen": {
+ "message": "加密你的新 DEN"
+ },
+ "enterPassword": {
+ "message": "請輸入密碼"
+ },
+ "enterPasswordConfirm": {
+ "message": "請再次輸入密碼確認"
+ },
+ "passwordNotLongEnough": {
+ "message": "您所輸入的密碼長度不足"
+ },
+ "passwordsDontMatch": {
+ "message": "您所輸入的密碼不一致"
+ },
+ "etherscanView": {
+ "message": "在 Etherscan 上查看帳戶"
+ },
+ "exchangeRate": {
+ "message": "匯率"
+ },
+ "exportPrivateKey": {
+ "message": "導出私鑰"
+ },
+ "exportPrivateKeyWarning": {
+ "message": "您需要自行負擔導出私鑰產生的風險"
+ },
+ "failed": {
+ "message": "失败"
+ },
+ "fiat": {
+ "message": "FIAT",
+ "description": "Exchange type"
+ },
+ "fileImportFail": {
+ "message": "檔案導入失敗?點擊這裡!",
+ "description": "Helps user import their account from a JSON file"
+ },
+ "followTwitter": {
+ "message": "追蹤 Twitter"
+ },
+ "from": {
+ "message": "來源地址"
+ },
+ "fromToSame": {
+ "message": "來源和目的地址不能一樣"
+ },
+ "fromShapeShift": {
+ "message": "來自 ShapeShift"
+ },
+ "gas": {
+ "message": "Gas",
+ "description": "Short indication of gas cost"
+ },
+ "gasFee": {
+ "message": "Gas 費用"
+ },
+ "gasLimit": {
+ "message": "Gas 上限"
+ },
+ "gasLimitCalculation": {
+ "message": "我們根據網路成功率算出建議的 Gas 上限。"
+ },
+ "gasLimitRequired": {
+ "message": "必需填寫 Gas 上限"
+ },
+ "gasLimitTooLow": {
+ "message": "Gas 上限至少為 21000"
+ },
+ "generatingSeed": {
+ "message": "產生助憶詞中..."
+ },
+ "gasPrice": {
+ "message": "Gas 價格 (GWEI)"
+ },
+ "gasPriceCalculation": {
+ "message": "我們根據網路成功率算出建議的 Gas 價格"
+ },
+ "gasPriceRequired": {
+ "message": "必需填寫 Gas 價格"
+ },
+ "getEther": {
+ "message": "取得 Ether"
+ },
+ "getEtherFromFaucet": {
+ "message": "從水管取得$1 Ether",
+ "description": "Displays network name for Ether faucet"
+ },
+ "greaterThanMin": {
+ "message": "必須要大於等於 $1。",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "here": {
+ "message": "這裡",
+ "description": "as in -click here- for more information (goes with troubleTokenBalances)"
+ },
+ "hereList": {
+ "message": "Here's a list!!!!"
+ },
+ "hide": {
+ "message": "隱藏"
+ },
+ "hideToken": {
+ "message": "隱藏代幣"
+ },
+ "hideTokenPrompt": {
+ "message": "隱藏代幣?"
+ },
+ "howToDeposit": {
+ "message": "你想怎麼存入 Ether?"
+ },
+ "holdEther": {
+ "message": "Metamask 讓您能保存 ether 和代幣, 並成為您接觸分散式應用程式的途徑."
+ },
+ "import": {
+ "message": "導入",
+ "description": "Button to import an account from a selected file"
+ },
+ "importAccount": {
+ "message": "導入帳戶"
+ },
+ "importAccountMsg": {
+ "message":" 匯入的帳戶與您原有 MetaMask 帳戶的助憶詞並無關聯. 請查看與導入帳戶相關的資料 "
+ },
+ "importAnAccount": {
+ "message": "導入一個帳戶"
+ },
+ "importDen": {
+ "message": "導入現成的 DEN"
+ },
+ "imported": {
+ "message": "已導入私鑰",
+ "description": "status showing that an account has been fully loaded into the keyring"
+ },
+ "infoHelp": {
+ "message": "說明 & 資訊"
+ },
+ "insufficientFunds": {
+ "message": "資金不足."
+ },
+ "insufficientTokens": {
+ "message": "代幣不足."
+ },
+ "invalidAddress": {
+ "message": "錯誤的地址"
+ },
+ "invalidAddressRecipient": {
+ "message": "接收地址錯誤"
+ },
+ "invalidGasParams": {
+ "message": "Gas 參數錯誤"
+ },
+ "invalidInput": {
+ "message": "輸入錯誤。"
+ },
+ "invalidRequest": {
+ "message": "無效的請求"
+ },
+ "invalidRPC": {
+ "message": "無效的 RPC URI"
+ },
+ "jsonFail": {
+ "message": "有東西出錯了. 請確認你的 JSON 檔案格式正確。"
+ },
+ "jsonFile": {
+ "message": "JSON 檔案",
+ "description": "format for importing an account"
+ },
+ "keepTrackTokens": {
+ "message": "持續追蹤您 MetaMask 帳戶中的代幣。"
+ },
+ "kovan": {
+ "message": "Kovan 測試網路"
+ },
+ "knowledgeDataBase": {
+ "message": "查看我們的知識庫"
+ },
+ "max": {
+ "message": "最大值"
+ },
+ "learnMore": {
+ "message": "了解更多。"
+ },
+ "lessThanMax": {
+ "message": "必須小於等於 $1.",
+ "description": "helper for inputting hex as decimal input"
+ },
+ "likeToAddTokens": {
+ "message": "您確定要加入這些代幣嗎?"
+ },
+ "links": {
+ "message": "連結"
+ },
+ "limit": {
+ "message": "上限"
+ },
+ "loading": {
+ "message": "載入..."
+ },
+ "loadingTokens": {
+ "message": "載入代幣..."
+ },
+ "localhost": {
+ "message": "Localhost 8545"
+ },
+ "login": {
+ "message": "登入"
+ },
+ "logout": {
+ "message": "登出"
+ },
+ "loose": {
+ "message": "非 MetaMask 帳號"
+ },
+ "loweCaseWords": {
+ "message": "助憶詞僅包含小寫字元"
+ },
+ "mainnet": {
+ "message": "乙太坊 主網路"
+ },
+ "message": {
+ "message": "訊息"
+ },
+ "metamaskDescription": {
+ "message": "MetaMask 是Ethereum的安全身份識別金庫."
+ },
+ "min": {
+ "message": "最小"
+ },
+ "myAccounts": {
+ "message": "我的帳戶"
+ },
+ "mustSelectOne": {
+ "message": "必須選擇至少 1 代幣."
+ },
+ "needEtherInWallet": {
+ "message": "要使用 MetaMask 存取 DAPP 時,您的錢包中需要有 Ether。"
+ },
+ "needImportFile": {
+ "message": "您必須選擇一個檔案來導入。",
+ "description": "User is important an account and needs to add a file to continue"
+ },
+ "needImportPassword": {
+ "message": "您必須為選擇好的檔案輸入密碼。",
+ "description": "Password and file needed to import an account"
+ },
+ "negativeETH": {
+ "message": "不能送出負值的 ETH。"
+ },
+ "networks": {
+ "message": "網路"
+ },
+ "newAccount": {
+ "message": "新帳戶"
+ },
+ "newAccountNumberName": {
+ "message": "帳戶 $1",
+ "description": "Default name of next account to be created on create account screen"
+ },
+ "newContract": {
+ "message": "新合約"
+ },
+ "newPassword": {
+ "message": "新密碼(至少8個字)"
+ },
+ "newRecipient": {
+ "message": "新收款人"
+ },
+ "newRPC": {
+ "message": "New RPC URL"
+ },
+ "next": {
+ "message": "下一頁"
+ },
+ "noAddressForName": {
+ "message": "此 ENS 尚未指定地址。"
+ },
+ "noDeposits": {
+ "message": "尚未有存款"
+ },
+ "noTransactionHistory": {
+ "message": "尚未有交易紀錄。"
+ },
+ "noTransactions": {
+ "message": "尚未有交易"
+ },
+ "notStarted": {
+ "message": "尚未開始"
+ },
+ "oldUI": {
+ "message": "舊版界面"
+ },
+ "oldUIMessage": {
+ "message": "你已經切換到舊版界面。可以通過右上方下拉選單中的選項切換回新的使用者界面。"
+ },
+ "or": {
+ "message": "或",
+ "description": "choice between creating or importing a new account"
+ },
+ "passwordCorrect": {
+ "message": "請確認您的密碼是正確的。"
+ },
+ "passwordMismatch": {
+ "message": "密碼不一致",
+ "description": "in password creation process, the two new password fields did not match"
+ },
+ "passwordShort": {
+ "message": "密碼不夠長",
+ "description": "in password creation process, the password is not long enough to be secure"
+ },
+ "pastePrivateKey": {
+ "message": "請貼上你的私鑰串:",
+ "description": "For importing an account from a private key"
+ },
+ "pasteSeed": {
+ "message": "請貼上你的助憶詞!"
+ },
+ "personalAddressDetected": {
+ "message": "已偵測到個人地址. 請輸入代幣合約地址."
+ },
+ "pleaseReviewTransaction": {
+ "message": "請檢查你的交易。"
+ },
+ "popularTokens": {
+ "message": "常見的代幣"
+ },
+ "privacyMsg": {
+ "message": "隱私政策"
+ },
+ "privateKey": {
+ "message": "私鑰",
+ "description": "select this type of file to use to import an account"
+ },
+ "privateKeyWarning": {
+ "message": "注意:永遠不要公開這個私鑰。任何取得這把私鑰的人都可以竊取這個帳號中的任何資產。"
+ },
+ "privateNetwork": {
+ "message": "私有網路"
+ },
+ "qrCode": {
+ "message": "顯示 QR Code"
+ },
+ "readdToken": {
+ "message": "之後還可以透過帳戶選單中的“加入代幣”來加入此代幣。"
+ },
+ "readMore": {
+ "message": "了解更多。"
+ },
+ "readMore2": {
+ "message": "了解更多。"
+ },
+ "receive": {
+ "message": "接收"
+ },
+ "recipientAddress": {
+ "message": "接收地址"
+ },
+ "refundAddress": {
+ "message": "你的退款地址"
+ },
+ "rejected": {
+ "message": "拒絕"
+ },
+ "resetAccount": {
+ "message": "重置帳戶"
+ },
+ "restoreFromSeed": {
+ "message": "透過助憶詞重置"
+ },
+ "restoreVault": {
+ "message": "重置金庫"
+ },
+ "required": {
+ "message": "必填"
+ },
+ "retryWithMoreGas": {
+ "message": "改用更高的 Gas 價格重試"
+ },
+ "walletSeed": {
+ "message": "錢包助憶詞"
+ },
+ "revealSeedWords": {
+ "message": "顯示助憶詞"
+ },
+ "revealSeedWordsWarning": {
+ "message": "別在公共場合回復你的助憶詞!這些詞可被用來竊取你的帳戶."
+ },
+ "revert": {
+ "message": "還原"
+ },
+ "rinkeby": {
+ "message": "Rinkeby 測試網路"
+ },
+ "ropsten": {
+ "message": "Ropsten 測試網路"
+ },
+ "currentRpc": {
+ "message": "當前的 RPC"
+ },
+ "connectingToMainnet": {
+ "message": "連線到主 Ethereum 網路"
+ },
+ "connectingToRopsten": {
+ "message": "連線到 Ropsten 測試網路"
+ },
+ "connectingToKovan": {
+ "message": "連線到 Kovan 測試網路"
+ },
+ "connectingToRinkeby": {
+ "message": "連線到 Rinkeby 測試網路"
+ },
+ "connectingToUnknown": {
+ "message": "連線到未知網路"
+ },
+ "sampleAccountName": {
+ "message": "例如:我的新帳戶",
+ "description": "Help user understand concept of adding a human-readable name to their account"
+ },
+ "save": {
+ "message": "儲存"
+ },
+ "saveAsFile": {
+ "message": "儲存檔案",
+ "description": "Account export process"
+ },
+ "saveSeedAsFile": {
+ "message": "將助憶詞儲存成檔案"
+ },
+ "search": {
+ "message": "搜尋"
+ },
+ "secretPhrase": {
+ "message": "在此輸入你的12個祕密助憶詞以回復金庫."
+ },
+ "newPassword8Chars": {
+ "message": "新密碼 (至少 8 個字元)"
+ },
+ "seedPhraseReq": {
+ "message": "助憶詞為 12 個詞語"
+ },
+ "select": {
+ "message": "選擇"
+ },
+ "selectCurrency": {
+ "message": "選擇幣別"
+ },
+ "selectService": {
+ "message": "選擇服務"
+ },
+ "selectType": {
+ "message": "選擇類型"
+ },
+ "send": {
+ "message": "發送"
+ },
+ "sendETH": {
+ "message": "發送 ETH"
+ },
+ "sendTokens": {
+ "message": "發送代幣"
+ },
+ "onlySendToEtherAddress": {
+ "message": "只發送 ETH 到乙太坊地址."
+ },
+ "searchTokens": {
+ "message": "搜尋代幣"
+ },
+ "sendTokensAnywhere": {
+ "message": "發送代幣給擁有乙太坊帳戶的任何人"
+ },
+ "settings": {
+ "message": "設定"
+ },
+ "info": {
+ "message": "資訊"
+ },
+ "shapeshiftBuy": {
+ "message": "從 Shapeshift 購買"
+ },
+ "showPrivateKeys": {
+ "message": "顯示私鑰"
+ },
+ "showQRCode": {
+ "message": "顯示 QR Code"
+ },
+ "sign": {
+ "message": "簽署"
+ },
+ "signed": {
+ "message": "已簽署"
+ },
+ "signMessage": {
+ "message": "簽署訊息"
+ },
+ "signNotice": {
+ "message": "簽署此訊息可能會產生危險地副作用。 \n只從你完全信任的網站上簽署。這種危險的方法;將在未來的版本中被移除。"
+ },
+ "sigRequest": {
+ "message": "請求簽署"
+ },
+ "sigRequested": {
+ "message": "已請求簽署"
+ },
+ "spaceBetween": {
+ "message": "there can only be a space between words"
+ },
+ "status": {
+ "message": "狀態"
+ },
+ "stateLogs": {
+ "message": "狀態紀錄"
+ },
+ "stateLogsDescription": {
+ "message": "狀態紀錄包含你的公開帳戶地址和已傳送的交易資訊."
+ },
+ "stateLogError": {
+ "message": "在取得狀態紀錄時發生錯誤."
+ },
+ "submit": {
+ "message": "送出"
+ },
+ "submitted": {
+ "message": "已送出"
+ },
+ "supportCenter": {
+ "message": "造訪我們的協助中心"
+ },
+ "symbolBetweenZeroTen": {
+ "message": "代號必須介於 0 到 10 字元間."
+ },
+ "takesTooLong": {
+ "message": "花費太長時間?"
+ },
+ "terms": {
+ "message": "使用條款"
+ },
+ "testFaucet": {
+ "message": "測試水管"
+ },
+ "to": {
+ "message": "目的帳號"
+ },
+ "toETHviaShapeShift": {
+ "message": "$1 ETH 透過 ShapeShift",
+ "description": "system will fill in deposit type in start of message"
+ },
+ "tokenAddress": {
+ "message": "代幣地址"
+ },
+ "tokenAlreadyAdded": {
+ "message": "已加入過此代幣。"
+ },
+ "tokenBalance": {
+ "message": "代幣餘額:"
+ },
+ "tokenSelection": {
+ "message": "搜尋代幣或是從常見代幣列表中選擇。"
+ },
+ "tokenSymbol": {
+ "message": "代幣代號"
+ },
+ "tokenWarning1": {
+ "message": "使用 MetaMask 帳戶追蹤你已購得的代幣。如果你使用不同的帳戶保存購得的代幣,那些代幣就不會出現在這裡。"
+ },
+ "total": {
+ "message": "總量"
+ },
+ "transactions": {
+ "message": "交易紀錄"
+ },
+ "transactionMemo": {
+ "message": "交易備註(選填)"
+ },
+ "transactionNumber": {
+ "message": "交易號碼"
+ },
+ "transfers": {
+ "message": "交易"
+ },
+ "troubleTokenBalances": {
+ "message": "無法取得代幣餘額。您k可以到這裡查看 ",
+ "description": "Followed by a link (here) to view token balances"
+ },
+ "twelveWords": {
+ "message": "這 12 個單詞是唯一回復你的 MetaMask 帳號的方法。\n將它們儲存到那些安全且隱密的地方吧。"
+ },
+ "typePassword": {
+ "message": "請輸入密碼"
+ },
+ "uiWelcome": {
+ "message": "歡迎使用新版界面 (Beta)"
+ },
+ "uiWelcomeMessage": {
+ "message": "你現在正在使用新版 MetaMask 界面。試試諸如發送代幣等新功能吧,有任何問題請告知我們。"
+ },
+ "unapproved": {
+ "message": "未同意"
+ },
+ "unavailable": {
+ "message": "不可用"
+ },
+ "unknown": {
+ "message": "未知"
+ },
+ "unknownNetwork": {
+ "message": "未知私有網路"
+ },
+ "unknownNetworkId": {
+ "message": "未知網路 ID"
+ },
+ "uriErrorMsg": {
+ "message": "URIs 需要加入適當的 HTTP/HTTPS 前綴."
+ },
+ "usaOnly": {
+ "message": "僅限美國",
+ "description": "Using this exchange is limited to people inside the USA"
+ },
+ "usedByClients": {
+ "message": "可用於各種不同的客戶端"
+ },
+ "useOldUI": {
+ "message": "使用舊版界面"
+ },
+ "validFileImport": {
+ "message": "您必須選擇一個合法的檔案來導入."
+ },
+ "vaultCreated": {
+ "message": "已建立金庫"
+ },
+ "viewAccount": {
+ "message": "查看帳戶"
+ },
+ "visitWebSite": {
+ "message": "造訪我們的網站"
+ },
+ "warning": {
+ "message": "警告"
+ },
+ "welcomeBeta": {
+ "message": "歡迎到 MetaMask Beta"
+ },
+ "whatsThis": {
+ "message": "這是什麼?"
+ },
+ "yourSigRequested": {
+ "message": "正在請求你的簽署"
+ },
+ "youSign": {
+ "message": "正在簽署"
+ }
+}
diff --git a/app/manifest.json b/app/manifest.json
index 0aac1c8df..a20f9b976 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "__MSG_appName__",
"short_name": "__MSG_appName__",
- "version": "4.3.0",
+ "version": "4.4.0",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "__MSG_appDescription__",
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 8bd7766ad..7782fc41e 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -19,7 +19,7 @@ const setupRaven = require('./lib/setupRaven')
const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry')
const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics')
const EdgeEncryptor = require('./edge-encryptor')
-
+const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code')
const STORAGE_KEY = 'metamask-config'
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
@@ -58,7 +58,8 @@ setupMetamaskMeshMetrics()
async function initialize () {
const initState = await loadStateFromPersistence()
- await setupController(initState)
+ const initLangCode = await getFirstPreferredLangCode()
+ await setupController(initState, initLangCode)
log.debug('MetaMask initialization complete.')
}
@@ -84,17 +85,16 @@ async function loadStateFromPersistence () {
// write to disk
if (localStore.isSupported) localStore.set(versionedData)
- diskStore.putState(versionedData)
// return just the data
return versionedData.data
}
-function setupController (initState) {
+function setupController (initState, initLangCode) {
//
// MetaMask Controller
//
-
+
const controller = new MetamaskController({
// User confirmation callbacks:
showUnconfirmedMessage: triggerUi,
@@ -102,6 +102,8 @@ function setupController (initState) {
showUnapprovedTx: triggerUi,
// initial state
initState,
+ // initial locale code
+ initLangCode,
// platform specific api
platform,
encryptor: isEdge ? new EdgeEncryptor() : undefined,
@@ -121,7 +123,6 @@ function setupController (initState) {
debounce(1000),
storeTransform(versionifyData),
storeTransform(syncDataWithExtension),
- asStream(diskStore),
(error) => {
log.error('pump hit error', error)
}
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index 39d15fd83..b4819d951 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -11,6 +11,7 @@ class PreferencesController {
tokens: [],
useBlockie: false,
featureFlags: {},
+ currentLocale: opts.initLangCode,
}, opts.initState)
this.store = new ObservableStore(initState)
}
@@ -24,6 +25,10 @@ class PreferencesController {
return this.store.getState().useBlockie
}
+ setCurrentLocale (key) {
+ this.store.updateState({ currentLocale: key })
+ }
+
setSelectedAddress (_address) {
return new Promise((resolve, reject) => {
const address = normalizeAddress(_address)
diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js
new file mode 100644
index 000000000..28612f763
--- /dev/null
+++ b/app/scripts/lib/get-first-preferred-lang-code.js
@@ -0,0 +1,16 @@
+const extension = require('extensionizer')
+const promisify = require('pify')
+const allLocales = require('../../_locales/index.json')
+
+const existingLocaleCodes = allLocales.map(locale => locale.code)
+
+async function getFirstPreferredLangCode () {
+ const userPreferredLocaleCodes = await promisify(
+ extension.i18n.getAcceptLanguages,
+ { errorFirst: false }
+ )()
+ const firstPreferredLangCode = userPreferredLocaleCodes.find(code => existingLocaleCodes.includes(code))
+ return firstPreferredLangCode || 'en'
+}
+
+module.exports = getFirstPreferredLangCode
diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js
index 42e48cb90..02c01b755 100644
--- a/app/scripts/lib/setupRaven.js
+++ b/app/scripts/lib/setupRaven.js
@@ -1,4 +1,4 @@
-const Raven = require('../vendor/raven.min.js')
+const Raven = require('raven-js')
const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG'
const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
@@ -18,9 +18,35 @@ function setupRaven(opts) {
ravenTarget = PROD
}
- Raven.config(ravenTarget, {
+ const client = Raven.config(ravenTarget, {
release,
- }).install()
+ transport: function(opts) {
+ // modify report urls
+ const report = opts.data
+ rewriteReportUrls(report)
+ // make request normally
+ client._makeRequest(opts)
+ },
+ })
+ client.install()
return Raven
}
+
+function rewriteReportUrls(report) {
+ // update request url
+ report.request.url = toMetamaskUrl(report.request.url)
+ // update exception stack trace
+ report.exception.values.forEach(item => {
+ item.stacktrace.frames.forEach(frame => {
+ frame.filename = toMetamaskUrl(frame.filename)
+ })
+ })
+}
+
+function toMetamaskUrl(origUrl) {
+ const filePath = origUrl.split(location.origin)[1]
+ if (!filePath) return origUrl
+ const metamaskUrl = `metamask${filePath}`
+ return metamaskUrl
+}
diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js
index ad07c813f..ab344ae9b 100644
--- a/app/scripts/lib/tx-state-manager.js
+++ b/app/scripts/lib/tx-state-manager.js
@@ -38,11 +38,6 @@ module.exports = class TransactionStateManager extends EventEmitter {
}, opts)
}
- // Returns the number of txs for the current network.
- getTxCount () {
- return this.getTxList().length
- }
-
getTxList () {
const network = this.getNetwork()
const fullTxList = this.getFullTxList()
@@ -88,7 +83,7 @@ module.exports = class TransactionStateManager extends EventEmitter {
txMeta.history.push(snapshot)
const transactions = this.getFullTxList()
- const txCount = this.getTxCount()
+ const txCount = transactions.length
const txHistoryLimit = this.txHistoryLimit
// checks if the length of the tx history is
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 18d71874a..ff7b66572 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -57,7 +57,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.defaultMaxListeners = 20
this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200)
-
+
this.opts = opts
const initState = opts.initState || {}
this.recordFirstTimeInfo(initState)
@@ -82,6 +82,7 @@ module.exports = class MetamaskController extends EventEmitter {
// preferences controller
this.preferencesController = new PreferencesController({
initState: initState.PreferencesController,
+ initLangCode: opts.initLangCode,
})
// currency controller
@@ -351,6 +352,7 @@ module.exports = class MetamaskController extends EventEmitter {
getState: (cb) => cb(null, this.getState()),
setCurrentCurrency: this.setCurrentCurrency.bind(this),
setUseBlockie: this.setUseBlockie.bind(this),
+ setCurrentLocale: this.setCurrentLocale.bind(this),
markAccountsFound: this.markAccountsFound.bind(this),
markPasswordForgotten: this.markPasswordForgotten.bind(this),
unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
@@ -1029,6 +1031,15 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
+ setCurrentLocale (key, cb) {
+ try {
+ this.preferencesController.setCurrentLocale(key)
+ cb(null)
+ } catch (err) {
+ cb(err)
+ }
+ }
+
recordFirstTimeInfo (initState) {
if (!('firstTimeInfo' in initState)) {
initState.firstTimeInfo = {
diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js
new file mode 100644
index 000000000..c3c0d53ef
--- /dev/null
+++ b/app/scripts/migrations/022.js
@@ -0,0 +1,39 @@
+
+const version = 22
+
+/*
+
+This migration adds submittedTime to the txMeta if it is not their
+
+*/
+
+const clone = require('clone')
+
+module.exports = {
+ version,
+
+ migrate: function (originalVersionedData) {
+ const versionedData = clone(originalVersionedData)
+ versionedData.meta.version = version
+ try {
+ const state = versionedData.data
+ const newState = transformState(state)
+ versionedData.data = newState
+ } catch (err) {
+ console.warn(`MetaMask Migration #${version}` + err.stack)
+ }
+ return Promise.resolve(versionedData)
+ },
+}
+
+function transformState (state) {
+ const newState = state
+ const transactions = newState.TransactionController.transactions
+
+ newState.TransactionController.transactions = transactions.map((txMeta) => {
+ if (txMeta.status !== 'submitted' || txMeta.submittedTime) return txMeta
+ txMeta.submittedTime = (new Date()).getTime()
+ return txMeta
+ })
+ return newState
+}
diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js
new file mode 100644
index 000000000..bce0a5bea
--- /dev/null
+++ b/app/scripts/migrations/023.js
@@ -0,0 +1,50 @@
+
+const version = 23
+
+/*
+
+This migration removes transactions that are no longer usefull down to 40 total
+
+*/
+
+const clone = require('clone')
+
+module.exports = {
+ version,
+
+ migrate: function (originalVersionedData) {
+ const versionedData = clone(originalVersionedData)
+ versionedData.meta.version = version
+ try {
+ const state = versionedData.data
+ const newState = transformState(state)
+ versionedData.data = newState
+ } catch (err) {
+ console.warn(`MetaMask Migration #${version}` + err.stack)
+ }
+ return Promise.resolve(versionedData)
+ },
+}
+
+function transformState (state) {
+ const newState = state
+ const transactions = newState.TransactionController.transactions
+
+ if (transactions.length <= 40) return newState
+
+ let reverseTxList = transactions.reverse()
+ let stripping = true
+ while (reverseTxList.length > 40 && stripping) {
+ let txIndex = reverseTxList.findIndex((txMeta) => {
+ return (txMeta.status === 'failed' ||
+ txMeta.status === 'rejected' ||
+ txMeta.status === 'confirmed' ||
+ txMeta.status === 'dropped')
+ })
+ if (txIndex < 0) stripping = false
+ else reverseTxList.splice(txIndex, 1)
+ }
+
+ newState.TransactionController.transactions = reverseTxList.reverse()
+ return newState
+}
diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js
index a0cf5f4d4..811e06b6b 100644
--- a/app/scripts/migrations/index.js
+++ b/app/scripts/migrations/index.js
@@ -32,4 +32,6 @@ module.exports = [
require('./019'),
require('./020'),
require('./021'),
+ require('./022'),
+ require('./023'),
]
diff --git a/app/scripts/popup.js b/app/scripts/popup.js
index e78981f06..13c7ac5ec 100644
--- a/app/scripts/popup.js
+++ b/app/scripts/popup.js
@@ -10,69 +10,75 @@ const NotificationManager = require('./lib/notification-manager')
const notificationManager = new NotificationManager()
const setupRaven = require('./lib/setupRaven')
-// create platform global
-global.platform = new ExtensionPlatform()
-
-// setup sentry error reporting
-const release = global.platform.getVersion()
-setupRaven({ release })
-
-// inject css
-// const css = MetaMaskUiCss()
-// injectCss(css)
-
-// identify window type (popup, notification)
-const windowType = isPopupOrNotification()
-global.METAMASK_UI_TYPE = windowType
-closePopupIfOpen(windowType)
-
-// setup stream to background
-const extensionPort = extension.runtime.connect({ name: windowType })
-const connectionStream = new PortStream(extensionPort)
-
-// start ui
-const container = document.getElementById('app-content')
-startPopup({ container, connectionStream }, (err, store) => {
- if (err) return displayCriticalError(err)
-
- // Code commented out until we begin auto adding users to NewUI
- // const { isMascara, identities = {}, featureFlags = {} } = store.getState().metamask
- // const firstTime = Object.keys(identities).length === 0
- const { isMascara, featureFlags = {} } = store.getState().metamask
- let betaUIState = featureFlags.betaUI
-
- // Code commented out until we begin auto adding users to NewUI
- // const useBetaCss = isMascara || firstTime || betaUIState
- const useBetaCss = isMascara || betaUIState
-
- let css = useBetaCss ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
- let deleteInjectedCss = injectCss(css)
- let newBetaUIState
-
- store.subscribe(() => {
- const state = store.getState()
- newBetaUIState = state.metamask.featureFlags.betaUI
- if (newBetaUIState !== betaUIState) {
- deleteInjectedCss()
- betaUIState = newBetaUIState
- css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
- deleteInjectedCss = injectCss(css)
- }
- if (state.appState.shouldClose) notificationManager.closePopup()
+start().catch(log.error)
+
+async function start() {
+
+ // create platform global
+ global.platform = new ExtensionPlatform()
+
+ // setup sentry error reporting
+ const release = global.platform.getVersion()
+ setupRaven({ release })
+
+ // inject css
+ // const css = MetaMaskUiCss()
+ // injectCss(css)
+
+ // identify window type (popup, notification)
+ const windowType = isPopupOrNotification()
+ global.METAMASK_UI_TYPE = windowType
+ closePopupIfOpen(windowType)
+
+ // setup stream to background
+ const extensionPort = extension.runtime.connect({ name: windowType })
+ const connectionStream = new PortStream(extensionPort)
+
+ // start ui
+ const container = document.getElementById('app-content')
+ startPopup({ container, connectionStream }, (err, store) => {
+ if (err) return displayCriticalError(err)
+
+ // Code commented out until we begin auto adding users to NewUI
+ // const { isMascara, identities = {}, featureFlags = {} } = store.getState().metamask
+ // const firstTime = Object.keys(identities).length === 0
+ const { isMascara, featureFlags = {} } = store.getState().metamask
+ let betaUIState = featureFlags.betaUI
+
+ // Code commented out until we begin auto adding users to NewUI
+ // const useBetaCss = isMascara || firstTime || betaUIState
+ const useBetaCss = isMascara || betaUIState
+
+ let css = useBetaCss ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
+ let deleteInjectedCss = injectCss(css)
+ let newBetaUIState
+
+ store.subscribe(() => {
+ const state = store.getState()
+ newBetaUIState = state.metamask.featureFlags.betaUI
+ if (newBetaUIState !== betaUIState) {
+ deleteInjectedCss()
+ betaUIState = newBetaUIState
+ css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
+ deleteInjectedCss = injectCss(css)
+ }
+ if (state.appState.shouldClose) notificationManager.closePopup()
+ })
})
-})
-function closePopupIfOpen (windowType) {
- if (windowType !== 'notification') {
- // should close only chrome popup
- notificationManager.closePopup()
+ function closePopupIfOpen (windowType) {
+ if (windowType !== 'notification') {
+ // should close only chrome popup
+ notificationManager.closePopup()
+ }
+ }
+
+ function displayCriticalError (err) {
+ container.innerHTML = '<div class="critical-error">The MetaMask app failed to load: please open and close MetaMask again to restart.</div>'
+ container.style.height = '80px'
+ log.error(err.stack)
+ throw err
}
-}
-function displayCriticalError (err) {
- container.innerHTML = '<div class="critical-error">The MetaMask app failed to load: please open and close MetaMask again to restart.</div>'
- container.style.height = '80px'
- log.error(err.stack)
- throw err
}
diff --git a/app/scripts/vendor/raven.min.js b/app/scripts/vendor/raven.min.js
deleted file mode 100644
index b439aeae6..000000000
--- a/app/scripts/vendor/raven.min.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/*! Raven.js 3.22.1 (7584197) | github.com/getsentry/raven-js */
-!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){function d(a){this.name="RavenConfigError",this.message=a}d.prototype=new Error,d.prototype.constructor=d,b.exports=d},{}],2:[function(a,b,c){var d=function(a,b,c){var d=a[b],e=a;if(b in a){var f="warn"===b?"warning":b;a[b]=function(){var a=[].slice.call(arguments),g=""+a.join(" "),h={level:f,logger:"console",extra:{arguments:a}};"assert"===b?a[0]===!1&&(g="Assertion failed: "+(a.slice(1).join(" ")||"console.assert"),h.extra.arguments=a.slice(1),c&&c(g,h)):c&&c(g,h),d&&Function.prototype.apply.call(d,e,a)}}};b.exports={wrapMethod:d}},{}],3:[function(a,b,c){(function(c){function d(){return+new Date}function e(a,b){return o(b)?function(c){return b(c,a)}:b}function f(){this.a=!("object"!=typeof JSON||!JSON.stringify),this.b=!n(K),this.c=!n(L),this.d=null,this.e=null,this.f=null,this.g=null,this.h=null,this.i=null,this.j={},this.k={release:J.SENTRY_RELEASE&&J.SENTRY_RELEASE.id,logger:"javascript",ignoreErrors:[],ignoreUrls:[],whitelistUrls:[],includePaths:[],headers:null,collectWindowErrors:!0,maxMessageLength:0,maxUrlLength:250,stackTraceLimit:50,autoBreadcrumbs:!0,instrument:!0,sampleRate:1},this.l={method:"POST",keepalive:!0,referrerPolicy:"origin"},this.m=0,this.n=!1,this.o=Error.stackTraceLimit,this.p=J.console||{},this.q={},this.r=[],this.s=d(),this.t=[],this.u=[],this.v=null,this.w=J.location,this.x=this.w&&this.w.href,this.y();for(var a in this.p)this.q[a]=this.p[a]}var g=a(6),h=a(7),i=a(1),j=a(5),k=j.isError,l=j.isObject,m=j.isErrorEvent,n=j.isUndefined,o=j.isFunction,p=j.isString,q=j.isArray,r=j.isEmptyObject,s=j.each,t=j.objectMerge,u=j.truncate,v=j.objectFrozen,w=j.hasKey,x=j.joinRegExp,y=j.urlencode,z=j.uuid4,A=j.htmlTreeAsString,B=j.isSameException,C=j.isSameStacktrace,D=j.parseUrl,E=j.fill,F=j.supportsFetch,G=a(2).wrapMethod,H="source protocol user pass host port path".split(" "),I=/^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/,J="undefined"!=typeof window?window:"undefined"!=typeof c?c:"undefined"!=typeof self?self:{},K=J.document,L=J.navigator;f.prototype={VERSION:"3.22.1",debug:!1,TraceKit:g,config:function(a,b){var c=this;if(c.g)return this.z("error","Error: Raven has already been configured"),c;if(!a)return c;var d=c.k;b&&s(b,function(a,b){"tags"===a||"extra"===a||"user"===a?c.j[a]=b:d[a]=b}),c.setDSN(a),d.ignoreErrors.push(/^Script error\.?$/),d.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/),d.ignoreErrors=x(d.ignoreErrors),d.ignoreUrls=!!d.ignoreUrls.length&&x(d.ignoreUrls),d.whitelistUrls=!!d.whitelistUrls.length&&x(d.whitelistUrls),d.includePaths=x(d.includePaths),d.maxBreadcrumbs=Math.max(0,Math.min(d.maxBreadcrumbs||100,100));var e={xhr:!0,console:!0,dom:!0,location:!0,sentry:!0},f=d.autoBreadcrumbs;"[object Object]"==={}.toString.call(f)?f=t(e,f):f!==!1&&(f=e),d.autoBreadcrumbs=f;var h={tryCatch:!0},i=d.instrument;return"[object Object]"==={}.toString.call(i)?i=t(h,i):i!==!1&&(i=h),d.instrument=i,g.collectWindowErrors=!!d.collectWindowErrors,c},install:function(){var a=this;return a.isSetup()&&!a.n&&(g.report.subscribe(function(){a.A.apply(a,arguments)}),a.B(),a.k.instrument&&a.k.instrument.tryCatch&&a.C(),a.k.autoBreadcrumbs&&a.D(),a.E(),a.n=!0),Error.stackTraceLimit=a.k.stackTraceLimit,this},setDSN:function(a){var b=this,c=b.F(a),d=c.path.lastIndexOf("/"),e=c.path.substr(1,d);b.G=a,b.h=c.user,b.H=c.pass&&c.pass.substr(1),b.i=c.path.substr(d+1),b.g=b.I(c),b.J=b.g+"/"+e+"api/"+b.i+"/store/",this.y()},context:function(a,b,c){return o(a)&&(c=b||[],b=a,a=void 0),this.wrap(a,b).apply(this,c)},wrap:function(a,b,c){function d(){var d=[],f=arguments.length,g=!a||a&&a.deep!==!1;for(c&&o(c)&&c.apply(this,arguments);f--;)d[f]=g?e.wrap(a,arguments[f]):arguments[f];try{return b.apply(this,d)}catch(h){throw e.K(),e.captureException(h,a),h}}var e=this;if(n(b)&&!o(a))return a;if(o(a)&&(b=a,a=void 0),!o(b))return b;try{if(b.L)return b;if(b.M)return b.M}catch(f){return b}for(var g in b)w(b,g)&&(d[g]=b[g]);return d.prototype=b.prototype,b.M=d,d.L=!0,d.N=b,d},uninstall:function(){return g.report.uninstall(),this.O(),this.P(),Error.stackTraceLimit=this.o,this.n=!1,this},captureException:function(a,b){var c=!k(a),d=!m(a),e=m(a)&&!a.error;if(c&&d||e)return this.captureMessage(a,t({trimHeadFrames:1,stacktrace:!0},b));m(a)&&(a=a.error),this.d=a;try{var f=g.computeStackTrace(a);this.Q(f,b)}catch(h){if(a!==h)throw h}return this},captureMessage:function(a,b){if(!this.k.ignoreErrors.test||!this.k.ignoreErrors.test(a)){b=b||{};var c,d=t({message:a+""},b);try{throw new Error(a)}catch(e){c=e}c.name=null;var f=g.computeStackTrace(c),h=q(f.stack)&&f.stack[1],i=h&&h.url||"";if((!this.k.ignoreUrls.test||!this.k.ignoreUrls.test(i))&&(!this.k.whitelistUrls.test||this.k.whitelistUrls.test(i))){if(this.k.stacktrace||b&&b.stacktrace){b=t({fingerprint:a,trimHeadFrames:(b.trimHeadFrames||0)+1},b);var j=this.R(f,b);d.stacktrace={frames:j.reverse()}}return this.S(d),this}}},captureBreadcrumb:function(a){var b=t({timestamp:d()/1e3},a);if(o(this.k.breadcrumbCallback)){var c=this.k.breadcrumbCallback(b);if(l(c)&&!r(c))b=c;else if(c===!1)return this}return this.u.push(b),this.u.length>this.k.maxBreadcrumbs&&this.u.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.r.push([a,b]),this.n&&this.E(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.T("extra",a),this},setTagsContext:function(a){return this.T("tags",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(h(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=e(b,a),this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=e(b,a),this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=e(b,a),this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.z("error","Error: Raven has not been configured.")),!1))},afterLoad:function(){var a=J.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(K){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new i("Missing eventId");var c=a.dsn||this.G;if(!c)throw new i("Missing DSN");var d=encodeURIComponent,e="";e+="?eventId="+d(b),e+="&dsn="+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+="&name="+d(f.name)),f.email&&(e+="&email="+d(f.email)));var g=this.I(this.F(c)),h=K.createElement("script");h.async=!0,h.src=g+"/api/embed/error-page/"+e,(K.head||K.body).appendChild(h)}},K:function(){var a=this;this.m+=1,setTimeout(function(){a.m-=1})},U:function(a,b){var c,d;if(this.b){b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),K.createEvent?(c=K.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=K.createEventObject(),c.eventType=a);for(d in b)w(b,d)&&(c[d]=b[d]);if(K.createEvent)K.dispatchEvent(c);else try{K.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}},V:function(a){var b=this;return function(c){if(b.W=null,b.v!==c){b.v=c;var d;try{d=A(c.target)}catch(e){d="<unknown>"}b.captureBreadcrumb({category:"ui."+a,message:d})}}},X:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&("INPUT"===f||"TEXTAREA"===f||d.isContentEditable)){var g=a.W;g||a.V("input")(c),clearTimeout(g),a.W=setTimeout(function(){a.W=null},b)}}},Y:function(a,b){var c=D(this.w.href),d=D(b),e=D(a);this.x=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:"navigation",data:{to:b,from:a}})},B:function(){var a=this;a.Z=Function.prototype.toString,Function.prototype.toString=function(){return"function"==typeof this&&this.L?a.Z.apply(this.N,arguments):a.Z.apply(this,arguments)}},O:function(){this.Z&&(Function.prototype.toString=this.Z)},C:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f<e.length;++f)e[f]=arguments[f];var g=e[0];return o(g)&&(e[0]=c.wrap(g)),a.apply?a.apply(this,e):a(e[0],e[1])}}function b(a){var b=J[a]&&J[a].prototype;b&&b.hasOwnProperty&&b.hasOwnProperty("addEventListener")&&(E(b,"addEventListener",function(b){return function(d,f,g,h){try{f&&f.handleEvent&&(f.handleEvent=c.wrap(f.handleEvent))}catch(i){}var j,k,l;return e&&e.dom&&("EventTarget"===a||"Node"===a)&&(k=c.V("click"),l=c.X(),j=function(a){if(a){var b;try{b=a.type}catch(c){return}return"click"===b?k(a):"keypress"===b?l(a):void 0}}),b.call(this,d,c.wrap(f,void 0,j),g,h)}},d),E(b,"removeEventListener",function(a){return function(b,c,d,e){try{c=c&&(c.M?c.M:c)}catch(f){}return a.call(this,b,c,d,e)}},d))}var c=this,d=c.t,e=this.k.autoBreadcrumbs;E(J,"setTimeout",a,d),E(J,"setInterval",a,d),J.requestAnimationFrame&&E(J,"requestAnimationFrame",function(a){return function(b){return a(c.wrap(b))}},d);for(var f=["EventTarget","Window","Node","ApplicationCache","AudioTrackList","ChannelMergerNode","CryptoOperation","EventSource","FileReader","HTMLUnknownElement","IDBDatabase","IDBRequest","IDBTransaction","KeyOperation","MediaController","MessagePort","ModalWindow","Notification","SVGElementInstance","Screen","TextTrack","TextTrackCue","TextTrackList","WebSocket","WebSocketWorker","Worker","XMLHttpRequest","XMLHttpRequestEventTarget","XMLHttpRequestUpload"],g=0;g<f.length;g++)b(f[g])},D:function(){function a(a,c){a in c&&o(c[a])&&E(c,a,function(a){return b.wrap(a)})}var b=this,c=this.k.autoBreadcrumbs,d=b.t;if(c.xhr&&"XMLHttpRequest"in J){var e=XMLHttpRequest.prototype;E(e,"open",function(a){return function(c,d){return p(d)&&d.indexOf(b.h)===-1&&(this.$={method:c,url:d,status_code:null}),a.apply(this,arguments)}},d),E(e,"send",function(c){return function(){function d(){if(e.$&&4===e.readyState){try{e.$.status_code=e.status}catch(a){}b.captureBreadcrumb({type:"http",category:"xhr",data:e.$})}}for(var e=this,f=["onload","onerror","onprogress"],g=0;g<f.length;g++)a(f[g],e);return"onreadystatechange"in e&&o(e.onreadystatechange)?E(e,"onreadystatechange",function(a){return b.wrap(a,void 0,d)}):e.onreadystatechange=d,c.apply(this,arguments)}},d)}c.xhr&&F()&&E(J,"fetch",function(a){return function(){for(var c=new Array(arguments.length),d=0;d<c.length;++d)c[d]=arguments[d];var e,f=c[0],g="GET";if("string"==typeof f?e=f:"Request"in J&&f instanceof J.Request?(e=f.url,f.method&&(g=f.method)):e=""+f,e.indexOf(b.h)!==-1)return a.apply(this,c);c[1]&&c[1].method&&(g=c[1].method);var h={method:g,url:e,status_code:null};return a.apply(this,c).then(function(a){return h.status_code=a.status,b.captureBreadcrumb({type:"http",category:"fetch",data:h}),a})}},d),c.dom&&this.b&&(K.addEventListener?(K.addEventListener("click",b.V("click"),!1),K.addEventListener("keypress",b.X(),!1)):(K.attachEvent("onclick",b.V("click")),K.attachEvent("onkeypress",b.X())));var f=J.chrome,g=f&&f.app&&f.app.runtime,h=!g&&J.history&&history.pushState&&history.replaceState;if(c.location&&h){var i=J.onpopstate;J.onpopstate=function(){var a=b.w.href;if(b.Y(b.x,a),i)return i.apply(this,arguments)};var j=function(a){return function(){var c=arguments.length>2?arguments[2]:void 0;return c&&b.Y(b.x,c+""),a.apply(this,arguments)}};E(history,"pushState",j,d),E(history,"replaceState",j,d)}if(c.console&&"console"in J&&console.log){var k=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:"console"})};s(["debug","info","warn","error","log"],function(a,b){G(console,b,k)})}},P:function(){for(var a;this.t.length;){a=this.t.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},E:function(){var a=this;s(this.r,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},F:function(a){var b=I.exec(a),c={},d=7;try{for(;d--;)c[H[d]]=b[d]||""}catch(e){throw new i("Invalid DSN: "+a)}if(c.pass&&!this.k.allowSecretKey)throw new i("Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key");return c},I:function(a){var b="//"+a.host+(a.port?":"+a.port:"");return a.protocol&&(b=a.protocol+":"+b),b},A:function(){this.m||this.Q.apply(this,arguments)},Q:function(a,b){var c=this.R(a,b);this.U("handle",{stackInfo:a,options:b}),this._(a.name,a.message,a.url,a.lineno,c,b)},R:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(s(a.stack,function(b,e){var f=c.aa(e,a.url);f&&d.push(f)}),b&&b.trimHeadFrames))for(var e=0;e<b.trimHeadFrames&&e<d.length;e++)d[e].in_app=!1;return d=d.slice(0,this.k.stackTraceLimit)},aa:function(a,b){var c={filename:a.url,lineno:a.line,colno:a.column,"function":a.func||"?"};return a.url||(c.filename=b),c.in_app=!(this.k.includePaths.test&&!this.k.includePaths.test(c.filename)||/(Raven|TraceKit)\./.test(c["function"])||/raven\.(min\.)?js$/.test(c.filename)),c},_:function(a,b,c,d,e,f){var g=(a?a+": ":"")+(b||"");if(!this.k.ignoreErrors.test||!this.k.ignoreErrors.test(b)&&!this.k.ignoreErrors.test(g)){var h;if(e&&e.length?(c=e[0].filename||c,e.reverse(),h={frames:e}):c&&(h={frames:[{filename:c,lineno:d,in_app:!0}]}),(!this.k.ignoreUrls.test||!this.k.ignoreUrls.test(c))&&(!this.k.whitelistUrls.test||this.k.whitelistUrls.test(c))){var i=t({exception:{values:[{type:a,value:b,stacktrace:h}]},culprit:c},f);this.S(i)}}},ba:function(a){var b=this.k.maxMessageLength;if(a.message&&(a.message=u(a.message,b)),a.exception){var c=a.exception.values[0];c.value=u(c.value,b)}var d=a.request;return d&&(d.url&&(d.url=u(d.url,this.k.maxUrlLength)),d.Referer&&(d.Referer=u(d.Referer,this.k.maxUrlLength))),a.breadcrumbs&&a.breadcrumbs.values&&this.ca(a.breadcrumbs),a},ca:function(a){for(var b,c,d,e=["to","from","url"],f=0;f<a.values.length;++f)if(c=a.values[f],c.hasOwnProperty("data")&&l(c.data)&&!v(c.data)){d=t({},c.data);for(var g=0;g<e.length;++g)b=e[g],d.hasOwnProperty(b)&&d[b]&&(d[b]=u(d[b],this.k.maxUrlLength));a.values[f].data=d}},da:function(){if(this.c||this.b){var a={};return this.c&&L.userAgent&&(a.headers={"User-Agent":navigator.userAgent}),J.location&&J.location.href&&(a.url=J.location.href),this.b&&K.referrer&&(a.headers||(a.headers={}),a.headers.Referer=K.referrer),a}},y:function(){this.ea=0,this.fa=null},ga:function(){return this.ea&&d()-this.fa<this.ea},ha:function(a){var b=this.e;return!(!b||a.message!==b.message||a.culprit!==b.culprit)&&(a.stacktrace||b.stacktrace?C(a.stacktrace,b.stacktrace):!a.exception&&!b.exception||B(a.exception,b.exception))},ia:function(a){if(!this.ga()){var b=a.status;if(400===b||401===b||429===b){var c;try{c=F()?a.headers.get("Retry-After"):a.getResponseHeader("Retry-After"),c=1e3*parseInt(c,10)}catch(e){}this.ea=c?c:2*this.ea||1e3,this.fa=d()}}},S:function(a){var b=this.k,c={project:this.i,logger:b.logger,platform:"javascript"},e=this.da();if(e&&(c.request=e),a.trimHeadFrames&&delete a.trimHeadFrames,a=t(c,a),a.tags=t(t({},this.j.tags),a.tags),a.extra=t(t({},this.j.extra),a.extra),a.extra["session:duration"]=d()-this.s,this.u&&this.u.length>0&&(a.breadcrumbs={values:[].slice.call(this.u,0)}),this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),Object.keys(a).forEach(function(b){(null==a[b]||""===a[b]||r(a[b]))&&delete a[b]}),o(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!r(a)&&(!o(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ga()?void this.z("warn","Raven dropped error due to backoff: ",a):void("number"==typeof b.sampleRate?Math.random()<b.sampleRate&&this.ja(a):this.ja(a))},ka:function(){return z()},ja:function(a,b){var c=this,d=this.k;if(this.isSetup()){if(a=this.ba(a),!this.k.allowDuplicates&&this.ha(a))return void this.z("warn","Raven dropped repeat event: ",a);this.f=a.event_id||(a.event_id=this.ka()),this.e=a,this.z("debug","Raven about to send:",a);var e={sentry_version:"7",sentry_client:"raven-js/"+this.VERSION,sentry_key:this.h};this.H&&(e.sentry_secret=this.H);var f=a.exception&&a.exception.values[0];this.k.autoBreadcrumbs&&this.k.autoBreadcrumbs.sentry&&this.captureBreadcrumb({category:"sentry",message:f?(f.type?f.type+": ":"")+f.value:a.message,event_id:a.event_id,level:a.level||"error"});var g=this.J;(d.transport||this.la).call(this,{url:g,auth:e,data:a,options:d,onSuccess:function(){c.y(),c.U("success",{data:a,src:g}),b&&b()},onError:function(d){c.z("error","Raven transport failed to send: ",d),d.request&&c.ia(d.request),c.U("failure",{data:a,src:g}),d=d||new Error("Raven send failed (no additional details provided)"),b&&b(d)}})}},la:function(a){var b=a.url+"?"+y(a.auth),c=null,d={};if(a.options.headers&&(c=this.ma(a.options.headers)),a.options.fetchParameters&&(d=this.ma(a.options.fetchParameters)),F()){d.body=h(a.data);var e=t({},this.l),f=t(e,d);return c&&(f.headers=c),J.fetch(b,f).then(function(b){if(b.ok)a.onSuccess&&a.onSuccess();else{var c=new Error("Sentry error code: "+b.status);c.request=b,a.onError&&a.onError(c)}})["catch"](function(){a.onError&&a.onError(new Error("Sentry error code: network unavailable"))})}var g=J.XMLHttpRequest&&new J.XMLHttpRequest;if(g){var i="withCredentials"in g||"undefined"!=typeof XDomainRequest;i&&("withCredentials"in g?g.onreadystatechange=function(){if(4===g.readyState)if(200===g.status)a.onSuccess&&a.onSuccess();else if(a.onError){var b=new Error("Sentry error code: "+g.status);b.request=g,a.onError(b)}}:(g=new XDomainRequest,b=b.replace(/^https?:/,""),a.onSuccess&&(g.onload=a.onSuccess),a.onError&&(g.onerror=function(){var b=new Error("Sentry error code: XDomainRequest");b.request=g,a.onError(b)})),g.open("POST",b),c&&s(c,function(a,b){g.setRequestHeader(a,b)}),g.send(h(a.data)))}},ma:function(a){var b={};for(var c in a)if(a.hasOwnProperty(c)){var d=a[c];b[c]="function"==typeof d?d():d}return b},z:function(a){this.q[a]&&this.debug&&Function.prototype.apply.call(this.q[a],this.p,[].slice.call(arguments,1))},T:function(a,b){n(b)?delete this.j[a]:this.j[a]=t(this.j[a]||{},b)}},f.prototype.setUser=f.prototype.setUserContext,f.prototype.setReleaseContext=f.prototype.setRelease,b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{1:1,2:2,5:5,6:6,7:7}],4:[function(a,b,c){(function(c){var d=a(3),e="undefined"!=typeof window?window:"undefined"!=typeof c?c:"undefined"!=typeof self?self:{},f=e.Raven,g=new d;g.noConflict=function(){return e.Raven=f,g},g.afterLoad(),b.exports=g}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{3:3}],5:[function(a,b,c){(function(a){function c(a){return"object"==typeof a&&null!==a}function d(a){switch({}.toString.call(a)){case"[object Error]":return!0;case"[object Exception]":return!0;case"[object DOMException]":return!0;default:return a instanceof Error}}function e(a){return l()&&"[object ErrorEvent]"==={}.toString.call(a)}function f(a){return void 0===a}function g(a){return"function"==typeof a}function h(a){return"[object Object]"===Object.prototype.toString.call(a)}function i(a){return"[object String]"===Object.prototype.toString.call(a)}function j(a){return"[object Array]"===Object.prototype.toString.call(a)}function k(a){if(!h(a))return!1;for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}function l(){try{return new ErrorEvent(""),!0}catch(a){return!1}}function m(){if(!("fetch"in E))return!1;try{return new Headers,new Request(""),new Response,!0}catch(a){return!1}}function n(a){function b(b,c){var d=a(b)||b;return c?c(d)||d:d}return b}function o(a,b){var c,d;if(f(a.length))for(c in a)s(a,c)&&b.call(null,c,a[c]);else if(d=a.length)for(c=0;c<d;c++)b.call(null,c,a[c])}function p(a,b){return b?(o(b,function(b,c){a[b]=c}),a):a}function q(a){return!!Object.isFrozen&&Object.isFrozen(a)}function r(a,b){return!b||a.length<=b?a:a.substr(0,b)+"…"}function s(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function t(a){for(var b,c=[],d=0,e=a.length;d<e;d++)b=a[d],i(b)?c.push(b.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")):b&&b.source&&c.push(b.source);return new RegExp(c.join("|"),"i")}function u(a){var b=[];return o(a,function(a,c){b.push(encodeURIComponent(a)+"="+encodeURIComponent(c))}),b.join("&")}function v(a){if("string"!=typeof a)return{};var b=a.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/),c=b[6]||"",d=b[8]||"";return{protocol:b[2],host:b[4],path:b[5],relative:b[5]+c+d}}function w(){var a=E.crypto||E.msCrypto;if(!f(a)&&a.getRandomValues){var b=new Uint16Array(8);a.getRandomValues(b),b[3]=4095&b[3]|16384,b[4]=16383&b[4]|32768;var c=function(a){for(var b=a.toString(16);b.length<4;)b="0"+b;return b};return c(b[0])+c(b[1])+c(b[2])+c(b[3])+c(b[4])+c(b[5])+c(b[6])+c(b[7])}return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"===a?b:3&b|8;return c.toString(16)})}function x(a){for(var b,c=5,d=80,e=[],f=0,g=0,h=" > ",i=h.length;a&&f++<c&&(b=y(a),!("html"===b||f>1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function y(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return"";if(g.push(a.tagName.toLowerCase()),a.id&&g.push("#"+a.id),b=a.className,b&&i(b))for(c=b.split(/\s+/),f=0;f<c.length;f++)g.push("."+c[f]);var h=["type","name","title","alt"];for(f=0;f<h.length;f++)d=h[f],e=a.getAttribute(d),e&&g.push("["+d+'="'+e+'"]');return g.join("")}function z(a,b){return!!(!!a^!!b)}function A(a,b){return f(a)&&f(b)}function B(a,b){return!z(a,b)&&(a=a.values[0],b=b.values[0],a.type===b.type&&a.value===b.value&&(!A(a.stacktrace,b.stacktrace)&&C(a.stacktrace,b.stacktrace)))}function C(a,b){if(z(a,b))return!1;var c=a.frames,d=b.frames;if(c.length!==d.length)return!1;for(var e,f,g=0;g<c.length;g++)if(e=c[g],f=d[g],e.filename!==f.filename||e.lineno!==f.lineno||e.colno!==f.colno||e["function"]!==f["function"])return!1;return!0}function D(a,b,c,d){var e=a[b];a[b]=c(e),a[b].L=!0,a[b].N=e,d&&d.push([a,b,e])}var E="undefined"!=typeof window?window:"undefined"!=typeof a?a:"undefined"!=typeof self?self:{};b.exports={isObject:c,isError:d,isErrorEvent:e,isUndefined:f,isFunction:g,isPlainObject:h,isString:i,isArray:j,isEmptyObject:k,supportsErrorEvent:l,supportsFetch:m,wrappedCallback:n,each:o,objectMerge:p,truncate:r,objectFrozen:q,hasKey:s,joinRegExp:t,urlencode:u,uuid4:w,htmlTreeAsString:x,htmlElementAsString:y,isSameException:B,isSameStacktrace:C,parseUrl:v,fill:D}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],6:[function(a,b,c){(function(c){function d(){return"undefined"==typeof document||null==document.location?"":document.location.href}var e=a(5),f={collectWindowErrors:!0,debug:!1},g="undefined"!=typeof window?window:"undefined"!=typeof c?c:"undefined"!=typeof self?self:{},h=[].slice,i="?",j=/^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;f.report=function(){function a(a){m(),s.push(a)}function b(a){for(var b=s.length-1;b>=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null,m=e.isErrorEvent(h)?h.error:h,n=e.isErrorEvent(a)?a.message:a;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,n),o();else if(m&&e.isError(m))l=f.computeStackTrace(m),k(l,!0);else{var p,r={url:b,line:c,column:g},s=void 0;if("[object String]"==={}.toString.call(n)){var p=n.match(j);p&&(s=p[1],n=p[2])}r.func=i,l={name:s,message:n,url:d(),stack:[r]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if("undefined"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,g=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,h=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,j=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,k=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=a.stack.split("\n"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n<o;++n){if(c=f.exec(l[n])){var p=c[2]&&0===c[2].indexOf("native"),q=c[2]&&0===c[2].indexOf("eval");q&&(b=k.exec(c[2]))&&(c[2]=b[1],c[3]=b[2],c[4]=b[3]),e={url:p?null:c[2],func:c[1]||i,args:p?[c[2]]:[],line:c[3]?+c[3]:null,column:c[4]?+c[4]:null}}else if(c=h.exec(l[n]))e={url:c[2],func:c[1]||i,args:[],line:+c[3],column:c[4]?+c[4]:null};else{if(!(c=g.exec(l[n])))continue;var q=c[3]&&c[3].indexOf(" > eval")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||"undefined"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(","):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),"undefined"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf("{"))}catch(p){}m[""+o]?n=!0:m[""+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){function d(a,b){for(var c=0;c<a.length;++c)if(a[c]===b)return c;return-1}function e(a,b,c,d){return JSON.stringify(a,g(b,d),c)}function f(a){var b={stack:a.stack,message:a.message,name:a.name};for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]=a[c]);return b}function g(a,b){var c=[],e=[];return null==b&&(b=function(a,b){return c[0]===b?"[Circular ~]":"[Circular ~."+e.slice(0,d(c,b)).join(".")+"]"}),function(g,h){if(c.length>0){var i=d(c,this);~i?c.splice(i+1):c.push(this),~i?e.splice(i,1/0,g):e.push(g),~d(c,h)&&(h=b.call(this,g,h))}else c.push(h);return null==a?h instanceof Error?f(h):h:a.call(this,g,h)}}c=b.exports=e,c.getSerialize=g},{}]},{},[4])(4)});
-//# sourceMappingURL=raven.min.js.map \ No newline at end of file