diff --git a/api/server.mjs b/api/server.mjs index 02050a2c..0c9b6100 100644 --- a/api/server.mjs +++ b/api/server.mjs @@ -18,6 +18,7 @@ import serveStatic from 'serve-static' import cors from 'cors' import favicon from 'express-favicon' import robots from 'express-robots-txt' +import { slowDown } from 'express-slow-down' import * as config from '#config' import * as routes from '#api/routes/index.mjs' @@ -70,6 +71,9 @@ api.use((req, res, next) => { const resourcesPath = path.join(__dirname, '..', 'resources') api.use('/resources', serveStatic(resourcesPath)) +const localesPath = path.join(__dirname, '..', 'locales') +api.use('/locales', serveStatic(localesPath)) + const dataPath = path.join(__dirname, '..', 'data') api.use('/data', serveStatic(dataPath)) @@ -95,9 +99,52 @@ api.use('/api/representatives', routes.representatives) api.use('/api/weight', routes.weight) const docsPath = path.join(__dirname, '..', 'docs') -api.use('/api/docs', serveStatic(docsPath)) -api.get('/api/docs/*', (req, res) => { - res.status(404).send('Not found') + +const speedLimiter = slowDown({ + windowMs: 10 * 60 * 1000, // 10 minutes + delayAfter: 50, // allow 50 requests per 10 minutes, then... + delayMs: 500, // begin adding 500ms of delay per request above 50: + maxDelayMs: 20000 // maximum delay of 20 seconds +}) + +api.use('/api/docs', speedLimiter, serveStatic(path.join(docsPath, 'en'))) +api.use('/api/docs/en', speedLimiter, serveStatic(path.join(docsPath, 'en'))) +api.get('/api/docs/:locale/*', speedLimiter, async (req, res) => { + const { locale } = req.params + const doc_id = req.params[0] // Capture the rest of the path as doc_id + const localized_doc_path = path.join(docsPath, locale, `${doc_id}.md`) + const default_doc_path = path.join(docsPath, 'en', `${doc_id}.md`) + + // check if paths are under the docs directory + if ( + !localized_doc_path.startsWith(docsPath) || + !default_doc_path.startsWith(docsPath) + ) { + return res.status(403).send('Forbidden') + } + + try { + if ( + await fs.promises + .access(localized_doc_path, fs.constants.F_OK) + .then(() => true) + .catch(() => false) + ) { + return res.sendFile(localized_doc_path) + } else if ( + await fs.promises + .access(default_doc_path, fs.constants.F_OK) + .then(() => true) + .catch(() => false) + ) { + return res.redirect(`/api/docs/en/${doc_id}`) + } else { + return res.status(404).send('Document not found') + } + } catch (error) { + console.error(error) + return res.status(500).send('Internal Server Error') + } }) api.use('/api/*', (err, req, res, next) => { diff --git a/docs/community.md b/docs/en/community.md similarity index 100% rename from docs/community.md rename to docs/en/community.md diff --git a/docs/contributing.md b/docs/en/contributing.md similarity index 100% rename from docs/contributing.md rename to docs/en/contributing.md diff --git a/docs/design/attack-vectors.md b/docs/en/design/attack-vectors.md similarity index 100% rename from docs/design/attack-vectors.md rename to docs/en/design/attack-vectors.md diff --git a/docs/design/basics.md b/docs/en/design/basics.md similarity index 100% rename from docs/design/basics.md rename to docs/en/design/basics.md diff --git a/docs/design/challenges.md b/docs/en/design/challenges.md similarity index 100% rename from docs/design/challenges.md rename to docs/en/design/challenges.md diff --git a/docs/design/glossary.md b/docs/en/design/glossary.md similarity index 100% rename from docs/design/glossary.md rename to docs/en/design/glossary.md diff --git a/docs/design/roadmap.md b/docs/en/design/roadmap.md similarity index 100% rename from docs/design/roadmap.md rename to docs/en/design/roadmap.md diff --git a/docs/design/security.md b/docs/en/design/security.md similarity index 100% rename from docs/design/security.md rename to docs/en/design/security.md diff --git a/docs/faqs.md b/docs/en/faqs.md similarity index 100% rename from docs/faqs.md rename to docs/en/faqs.md diff --git a/docs/getting-started-devs/adding-custom-stats.md b/docs/en/getting-started-devs/adding-custom-stats.md similarity index 100% rename from docs/getting-started-devs/adding-custom-stats.md rename to docs/en/getting-started-devs/adding-custom-stats.md diff --git a/docs/getting-started-devs/developer-discussions.md b/docs/en/getting-started-devs/developer-discussions.md similarity index 100% rename from docs/getting-started-devs/developer-discussions.md rename to docs/en/getting-started-devs/developer-discussions.md diff --git a/docs/getting-started-devs/documentation.md b/docs/en/getting-started-devs/documentation.md similarity index 100% rename from docs/getting-started-devs/documentation.md rename to docs/en/getting-started-devs/documentation.md diff --git a/docs/getting-started-devs/getting-started.md b/docs/en/getting-started-devs/getting-started.md similarity index 100% rename from docs/getting-started-devs/getting-started.md rename to docs/en/getting-started-devs/getting-started.md diff --git a/docs/getting-started-devs/integrations.md b/docs/en/getting-started-devs/integrations.md similarity index 100% rename from docs/getting-started-devs/integrations.md rename to docs/en/getting-started-devs/integrations.md diff --git a/docs/getting-started-devs/protocol-reference.md b/docs/en/getting-started-devs/protocol-reference.md similarity index 100% rename from docs/getting-started-devs/protocol-reference.md rename to docs/en/getting-started-devs/protocol-reference.md diff --git a/docs/getting-started-devs/running-a-node.md b/docs/en/getting-started-devs/running-a-node.md similarity index 100% rename from docs/getting-started-devs/running-a-node.md rename to docs/en/getting-started-devs/running-a-node.md diff --git a/docs/getting-started-devs/tutorials/overview.md b/docs/en/getting-started-devs/tutorials/overview.md similarity index 100% rename from docs/getting-started-devs/tutorials/overview.md rename to docs/en/getting-started-devs/tutorials/overview.md diff --git a/docs/getting-started-users/acquiring.md b/docs/en/getting-started-users/acquiring.md similarity index 100% rename from docs/getting-started-users/acquiring.md rename to docs/en/getting-started-users/acquiring.md diff --git a/docs/getting-started-users/basics.md b/docs/en/getting-started-users/basics.md similarity index 100% rename from docs/getting-started-users/basics.md rename to docs/en/getting-started-users/basics.md diff --git a/docs/getting-started-users/best-practices.md b/docs/en/getting-started-users/best-practices.md similarity index 100% rename from docs/getting-started-users/best-practices.md rename to docs/en/getting-started-users/best-practices.md diff --git a/docs/getting-started-users/choosing-a-representative.md b/docs/en/getting-started-users/choosing-a-representative.md similarity index 100% rename from docs/getting-started-users/choosing-a-representative.md rename to docs/en/getting-started-users/choosing-a-representative.md diff --git a/docs/getting-started-users/privacy.md b/docs/en/getting-started-users/privacy.md similarity index 100% rename from docs/getting-started-users/privacy.md rename to docs/en/getting-started-users/privacy.md diff --git a/docs/getting-started-users/storing/basics.md b/docs/en/getting-started-users/storing/basics.md similarity index 100% rename from docs/getting-started-users/storing/basics.md rename to docs/en/getting-started-users/storing/basics.md diff --git a/docs/getting-started-users/storing/setup.md b/docs/en/getting-started-users/storing/setup.md similarity index 100% rename from docs/getting-started-users/storing/setup.md rename to docs/en/getting-started-users/storing/setup.md diff --git a/docs/getting-started-users/using.md b/docs/en/getting-started-users/using.md similarity index 100% rename from docs/getting-started-users/using.md rename to docs/en/getting-started-users/using.md diff --git a/docs/history/community/nano-trade.md b/docs/en/history/community/nano-trade.md similarity index 100% rename from docs/history/community/nano-trade.md rename to docs/en/history/community/nano-trade.md diff --git a/docs/history/overview.md b/docs/en/history/overview.md similarity index 100% rename from docs/history/overview.md rename to docs/en/history/overview.md diff --git a/docs/introduction/advantages.md b/docs/en/introduction/advantages.md similarity index 100% rename from docs/introduction/advantages.md rename to docs/en/introduction/advantages.md diff --git a/docs/introduction/basics.md b/docs/en/introduction/basics.md similarity index 100% rename from docs/introduction/basics.md rename to docs/en/introduction/basics.md diff --git a/docs/introduction/how-it-works.md b/docs/en/introduction/how-it-works.md similarity index 100% rename from docs/introduction/how-it-works.md rename to docs/en/introduction/how-it-works.md diff --git a/docs/introduction/investment-thesis.md b/docs/en/introduction/investment-thesis.md similarity index 100% rename from docs/introduction/investment-thesis.md rename to docs/en/introduction/investment-thesis.md diff --git a/docs/introduction/misconceptions.md b/docs/en/introduction/misconceptions.md similarity index 100% rename from docs/introduction/misconceptions.md rename to docs/en/introduction/misconceptions.md diff --git a/docs/introduction/why-it-matters.md b/docs/en/introduction/why-it-matters.md similarity index 100% rename from docs/introduction/why-it-matters.md rename to docs/en/introduction/why-it-matters.md diff --git a/docs/labels.md b/docs/en/labels.md similarity index 100% rename from docs/labels.md rename to docs/en/labels.md diff --git a/docs/labels/attack-vectors.md b/docs/en/labels/attack-vectors.md similarity index 100% rename from docs/labels/attack-vectors.md rename to docs/en/labels/attack-vectors.md diff --git a/docs/labels/congestion-spam.md b/docs/en/labels/congestion-spam.md similarity index 100% rename from docs/labels/congestion-spam.md rename to docs/en/labels/congestion-spam.md diff --git a/docs/labels/consensus.md b/docs/en/labels/consensus.md similarity index 100% rename from docs/labels/consensus.md rename to docs/en/labels/consensus.md diff --git a/docs/labels/economics.md b/docs/en/labels/economics.md similarity index 100% rename from docs/labels/economics.md rename to docs/en/labels/economics.md diff --git a/docs/labels/finality.md b/docs/en/labels/finality.md similarity index 100% rename from docs/labels/finality.md rename to docs/en/labels/finality.md diff --git a/docs/labels/governance.md b/docs/en/labels/governance.md similarity index 100% rename from docs/labels/governance.md rename to docs/en/labels/governance.md diff --git a/docs/labels/micropayments.md b/docs/en/labels/micropayments.md similarity index 100% rename from docs/labels/micropayments.md rename to docs/en/labels/micropayments.md diff --git a/docs/labels/minimum-account-balances.md b/docs/en/labels/minimum-account-balances.md similarity index 100% rename from docs/labels/minimum-account-balances.md rename to docs/en/labels/minimum-account-balances.md diff --git a/docs/labels/privacy.md b/docs/en/labels/privacy.md similarity index 100% rename from docs/labels/privacy.md rename to docs/en/labels/privacy.md diff --git a/docs/labels/scalability.md b/docs/en/labels/scalability.md similarity index 100% rename from docs/labels/scalability.md rename to docs/en/labels/scalability.md diff --git a/docs/labels/security.md b/docs/en/labels/security.md similarity index 100% rename from docs/labels/security.md rename to docs/en/labels/security.md diff --git a/docs/labels/tx-prioritization/dpow.md b/docs/en/labels/tx-prioritization/dpow.md similarity index 100% rename from docs/labels/tx-prioritization/dpow.md rename to docs/en/labels/tx-prioritization/dpow.md diff --git a/docs/labels/tx-prioritization/fee.md b/docs/en/labels/tx-prioritization/fee.md similarity index 100% rename from docs/labels/tx-prioritization/fee.md rename to docs/en/labels/tx-prioritization/fee.md diff --git a/docs/labels/tx-prioritization/taac-pos4qos.md b/docs/en/labels/tx-prioritization/taac-pos4qos.md similarity index 100% rename from docs/labels/tx-prioritization/taac-pos4qos.md rename to docs/en/labels/tx-prioritization/taac-pos4qos.md diff --git a/docs/labels/wallets.md b/docs/en/labels/wallets.md similarity index 100% rename from docs/labels/wallets.md rename to docs/en/labels/wallets.md diff --git a/docs/okrs.md b/docs/en/okrs.md similarity index 100% rename from docs/okrs.md rename to docs/en/okrs.md diff --git a/docs/support.md b/docs/en/support.md similarity index 100% rename from docs/support.md rename to docs/en/support.md diff --git a/locales/ar.json b/locales/ar.json new file mode 100644 index 00000000..e82a55fe --- /dev/null +++ b/locales/ar.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "عنوان الحساب", + "change_summary": "تغيير الملخص", + "copy_notification": "تم نسخ عنوان الحساب", + "seo_description": "معلومات لممثل نانو", + "seo_title": "حساب نانو", + "telemetry_charts": "رسوم بيانية للقياس عن بعد", + "unopened_description": "بينما يكون عنوان الحساب صالحًا، لم يتم ملاحظة أي كتل. إذا تم إرسال NANO إلى هذا الحساب، لا يزال يتعين نشر كتلة مقابلة لاستلام الأموال وإنشاء رصيد افتتاحي. يمكن فقط تحديث رصيد الحساب من قبل صاحب الحساب لأنهم فقط يمكنهم نشر الكتل على سلسلتهم.", + "unopened_note": "إذا تم بالفعل نشر كتلة افتتاحية، قد يستغرق الأمر بضع لحظات لتنتشر عبر الشبكة ويتم ملاحظتها من قبل عقد nano.community.", + "unopened_title": "لم يتم فتح هذا الحساب بعد" + }, + "account_blocks_summary": { + "first_timestamp": "أول طابع زمني", + "last_timestamp": "آخر طابع زمني", + "max_amount": "الحد الأقصى للمبلغ", + "min_amount": "الحد الأدنى للمبلغ", + "no_records": "لا توجد سجلات", + "receiving_account": "استقبال الحساب", + "representative_account": "حساب الممثل", + "sending_account": "إرسال الحساب", + "showing_top_10": "عرض أفضل 10 حسابات حسب المجموع تنازليًا", + "transactions": "المعاملات" + }, + "account_meta": { + "account_info": "معلومات الحساب", + "funding_account": "حساب التمويل", + "funding_timestamp": "طابع زمني للتمويل", + "height": "الارتفاع", + "last_modified": "آخر تعديل", + "open_timestamp": "طابع زمني للفتح", + "opening_balance": "الرصيد الافتتاحي", + "receivable_balance": "الرصيد القابل للتحصيل" + }, + "block_page": { + "amount": "المبلغ", + "copy_notification": "تم نسخ هاش الكتلة", + "delegated_representative": "الممثل المفوض", + "description": "الوصف", + "epoch_v1": "العصر v1 - تم تحديث سلاسل حسابات من الكتل القديمة (فتح، استلام، إرسال، تغيير) إلى كتل الحالة.", + "epoch_v2": "العصر v2 - تم تحديث سلاسل الحسابات لاستخدام صعوبة إثبات العمل الأعلى.", + "receiving_account": "استقبال الحساب", + "section_label": "هاش الكتلة", + "sending_account": "إرسال الحساب", + "seo_description": "معلومات متعلقة بكتلة نانو", + "seo_title": "كتلة نانو", + "voting_weight": "وزن التصويت" + }, + "block_info": { + "block_account": "حساب الكتلة", + "operation": "العملية", + "status": "الحالة", + "timestamp": "الطابع الزمني" + }, + "block_status": { + "confirmed": "مؤكد", + "unconfirmed": "غير مؤكد" + }, + "block_type": { + "change": "تغيير", + "epoch": "عصر", + "open": "فتح", + "receive": "استلام", + "send": "إرسال" + }, + "common": { + "account_one": "حساب", + "account_other": "حسابات", + "address": "العنوان", + "balance": "الرصيد", + "bandwidth_limit": "حد النطاق الترددي", + "bandwidth_limit_short": "حد النطاق", + "blocks": "الكتل", + "blocks_behind": "الكتل المتأخرة", + "blocks_diff_short": "فرق الكتل", + "by_online_weight": "حسب الوزن عبر الإنترنت", + "clear_filters": "مسح الفلاتر", + "click_to_copy": "انقر للنسخ", + "collapse": "طي", + "conf_short": "تأكيد", + "conf_diff_short": "فرق التأكيد", + "confirmations_behind": "التأكيدات المتأخرة", + "country": "البلد", + "delegator_one": "مفوض", + "delegator_other": "مفوضون", + "max": "الأقصى", + "min": "الأدنى", + "offline": "غير متصل", + "online": "متصل", + "peers": "الأقران", + "percent_of_total": "% من الإجمالي", + "port": "المنفذ", + "quorum_delta": "فارق النصاب", + "representative_one": "ممثل", + "representative_other": "ممثلون", + "show_more": "عرض {{count}} المزيد", + "total": "المجموع", + "unchecked": "غير مفحوص", + "unchecked_count": "عدد غير المفحوص", + "unlimited": "غير محدود", + "uptime": "وقت التشغيل", + "version": "الإصدار", + "weight": "الوزن" + }, + "delegators": { + "showing_top_delegators": "عرض أفضل 100 مفوض بحد أدنى للرصيد 1 نانو." + }, + "doc": { + "contributors": "مساهم", + "document_not_found": "الوثيقة (أو الحساب) غير موجودة", + "edit_page": "تعديل الصفحة", + "help_out": "ساعد", + "not_found_404": "404", + "section_link_copied": "تم نسخ رابط القسم", + "updated_by": "تم التحديث بواسطة" + }, + "github_events": { + "action": { + "added_member": "أضاف عضو", + "commented_on_commit": "علق على الالتزام", + "commented_on_issue": "علق على المشكلة", + "commented_on_pr_review": "علق على مراجعة طلب السحب", + "created": "أنشأ {{action}}", + "deleted": "حذف {{action}}", + "forked": "تفرع", + "issue_action": "{{action}} مشكلة", + "made_public": "جعله عام", + "pr_action": "{{action}} طلب سحب", + "pr_review": "مراجعة طلب السحب {{title}}", + "published_release": "نشر إصدار", + "pushed_commit": "دفع التزام إلى {{ref}}", + "sponsorship_started": "بدأ الرعاية", + "watching_repo": "مشاهدة المستودع" + }, + "events_title": "أحداث التطوير" + }, + "ledger": { + "addresses": { + "active_detail": "يظهر النشط عدد العناوين الفريدة المستخدمة. يظهر الجديد عدد العناوين التي تم إنشاؤها. يظهر المعاد استخدامه عدد العناوين المستخدمة التي تم إنشاؤها في يوم سابق.", + "active_stats": "إحصائيات العناوين النشطة", + "new_stats": "إحصائيات العناوين الجديدة", + "total_number": "العدد الإجمالي للعناوين النشطة والجديدة والمعاد استخدامها المستخدمة يوميًا." + }, + "amounts": { + "total_number": "عدد الكتل المؤكدة من نوع الإرسال يوميًا حيث يكون المبلغ في الكتلة ضمن نطاق معين (بالنانو)" + }, + "blocks": { + "change": "إحصائيات كتل التغيير", + "description": "عدد الكتل المؤكدة يوميًا.", + "open": "إحصائيات كتل الفتح", + "receive": "إحصائيات كتل الاستلام", + "send": "إحصائيات كتل الإرسال", + "total": "إحصائيات الكتل الإجمالية" + }, + "description": "الوصف", + "usd_transferred": { + "desc_1": "المبلغ الإجمالي للقيمة المنقولة (بالدولار الأمريكي) يوميًا.", + "desc_2": "بناءً على سعر الإغلاق اليومي للنانو/الدولار الأمريكي والمبلغ الإجمالي للنانو المنقول في ذلك اليوم.", + "usd_transferred": "الدولار الأمريكي المنقول", + "usd_transferred_stats": "إحصائيات الدولار الأمريكي المنقول" + }, + "volume": { + "change_stats": "إحصائيات التغيير", + "description": "المبلغ الإجمالي المرسل (بالنانو) والمبلغ الإجمالي لوزن التصويت المتغير يوميًا.", + "send_stats": "إحصائيات الإرسال" + } + }, + "ledger_page": { + "addresses_tab": "العناوين", + "amounts_tab": "المبالغ", + "blocks_tab": "الكتل", + "seo_description": "مقاييس وتحليلات سلسلة الكتل نانو", + "seo_title": "تحليل سلسلة كتل نانو", + "value_transferred_tab": "القيمة المنقولة", + "volume_tab": "الحجم" + }, + "menu": { + "account_setup": "إعداد الحساب", + "acquiring": "الحصول", + "advantages": "المزايا", + "attack_vectors": "نقاط الهجوم", + "basics": "الأساسيات", + "best_practices": "أفضل الممارسات", + "choosing_a_rep": "اختيار ممثل", + "challenges": "التحديات", + "communities": "المجتمعات", + "contribution_guide": "دليل المساهمة", + "design": "التصميم", + "developer_discussions": "مناقشات المطورين", + "developers": "المطورون", + "documentation": "التوثيق", + "faqs": "الأسئلة الشائعة", + "get_involved": "شارك", + "get_support": "احصل على الدعم", + "getting_started": "البدء", + "glossary": "المعجم", + "guides": "الأدلة", + "history": "التاريخ", + "home": "الرئيسية", + "how_it_works": "كيف يعمل", + "integrations": "التكاملات", + "introduction": "المقدمة", + "investment_thesis": "أطروحة الاستثمار", + "learn": "تعلم", + "ledger": "السجل", + "misconceptions": "المفاهيم الخاطئة", + "overview": "نظرة عامة", + "planning": "التخطيط 👾", + "privacy": "الخصوصية", + "protocol": "البروتوكول", + "running_a_node": "تشغيل عقدة", + "security": "الأمان", + "stats": "الإحصائيات", + "storing": "التخزين", + "telemetry": "قياس عن بعد", + "topics": "المواضيع", + "using": "الاستخدام", + "why_it_matters": "لماذا يهم" + }, + "network": { + "backlog_text": "العدد الوسيط للمعاملات المنتظر تأكيدها $(network.pr_text)", + "censor_text": "الحد الأدنى لعدد الممثلين المطلوبين لرقابة المعاملات أو تعطيل الشبكة", + "confirm_text": "الحد الأدنى لعدد الممثلين المطلوبين لتأكيد المعاملات", + "confirmations": "التأكيدات (24 ساعة)", + "confirmations_text": "إجمالي عدد المعاملات التي أكدتها الشبكة خلال الـ 24 ساعة الماضية", + "energy_text": "الاستخدام التقديري لطاقة وحدة المعالجة المركزية للشبكة الحية للممثلين الرئيسيين بناءً على معلومات نموذج وحدة المعالجة المركزية المجمعة. التقدير مبني على TDP وحدة المعالجة المركزية، وهو الطاقة المتوسطة بالواط، التي تبددها المعالجة عند التشغيل بتردد الأساس مع تفعيل جميع النوى تحت حمل عمل معقد محدد من قبل الشركة المصنعة", + "energy_usage": "استخدام الطاقة (TDP) (24 ساعة)", + "fee_text": "شبكة النانو تعمل بدون رسوم", + "nano_ticker": "مؤشر النانو", + "online_stake": "الحصة المتصلة", + "principal_reps": "الممثلون الرئيسيون", + "pr_text": "كما لوحظ عبر الممثلين الرئيسيين للشبكات: العقد التي تمتلك أكثر من 0.1% من وزن التصويت عبر الإنترنت الموكلة إليها", + "reps_to_censor": "الممثلون للرقابة أو التعطيل", + "reps_to_confirm": "الممثلون للتأكيد", + "settlement": "التسوية (24 ساعة)", + "settlement_text": "إجمالي قيمة التسوية التي قامت بها الشبكة خلال الـ 24 ساعة الماضية", + "speed_text": "الوقت بالملي ثانية لتأكيد معاملة اختبارية", + "stake_text": "نسبة وزن نانو الموكلة التي تشارك بنشاط في التصويت", + "stats_title": "إحصائيات الشبكة", + "total_reps": "إجمالي الممثلين (24 ساعة)", + "tx_backlog": "تراكم المعاملات", + "tx_fees": "رسوم المعاملات (24 ساعة)", + "tx_speed": "سرعة المعاملة", + "tx_throughput": "إنتاجية المعاملة", + "throughput_text": "العدد الوسيط للمعاملات المؤكدة في الثانية خلال الدقيقة الأخيرة $(network.pr_text)" + }, + "posts": { + "nano_foundation": "مؤسسة نانو", + "top": "الأعلى", + "trending": "الشائع" + }, + "representative_alerts": { + "table_header": { + "behind": "متأخر", + "issue": "مشكلة", + "last_online": "آخر ظهور على الإنترنت", + "percent_online_weight": "% وزن متصل", + "representative": "الممثل" + }, + "tooltip": { + "behind": "الممثل متأخر أو يقوم بالتمهيد. الحد هو عدد مؤكد يتجاوز النسبة المئوية 95. (عبر القياس عن بعد)", + "low_uptime": "الممثل كان متوقفًا عن العمل أكثر من 25% في آخر 28 يومًا.", + "offline": "الممثل توقف عن التصويت ويبدو غير متصل.", + "overweight": "الممثل يمتلك وزن تصويت يتجاوز 3 مليون نانو. يجب على المفوضين النظر في توزيع الوزن لتحسين مرونة الشبكة وقيمتها." + }, + "type": { + "behind": "متأخر", + "low_uptime": "وقت تشغيل منخفض", + "offline": "غير متصل", + "overweight": "زيادة الوزن" + } + }, + "representatives_cemented_by_weight": { + "title": "الفرق في التأكيد", + "tooltip": "يعرض كمية وزن التصويت التي تقع ضمن عدد X من التأكيدات من العقدة الرائدة. مفيد في معرفة مدى تزامن العقد وتوافقها عبر الشبكة" + }, + "representatives_checked_by_weight": { + "title": "الفرق في الكتل", + "tooltip": "يعرض كمية وزن التصويت التي تقع ضمن عدد X من الكتل من العقدة الرائدة. مفيد للحصول على فكرة عن مدى تزامن انتشار الكتل داخل الشبكة" + }, + "representative_delegators": { + "showing_top_delegators": "يعرض أفضل 100 مفوض بحد أدنى رصيد 1 نانو." + }, + "representative_info": { + "first_seen": "أول ظهور", + "last_seen": "آخر ظهور", + "weight_represented": "الوزن الممثل" + }, + "representative_network": { + "city": "المدينة", + "isp": "مزود الخدمة", + "network": "الشبكة", + "provider": "المزود" + }, + "representative_telemetry": { + "telemetry": "القياس عن بعد", + "telemetry_timestamp": "طابع زمني للقياس عن بعد" + }, + "representative_uptime": { + "2m_uptime": "وقت التشغيل 2 شهر", + "2w_uptime": "وقت التشغيل 2 أسبوع", + "3m_uptime": "وقت التشغيل 3 أشهر", + "current_status": "الحالة الحالية", + "down": "متوقف", + "down_for": "متوقف منذ", + "operational": "تشغيلي", + "up_for": "يعمل منذ", + "warning": "تحذير" + }, + "representatives": { + "alias": "الاسم المستعار", + "cpu_cores": "أنوية المعالج", + "cpu_model": "طراز المعالج", + "tdp": "TDP (واط ساعة)", + "protocol_version": "البروتوكول", + "last_seen": "آخر ظهور", + "host_asn": "ASN المضيف" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "يعرض كمية وزن التصويت بناءً على حد النطاق الترددي المحدد محليًا بواسطة كل عقدة" + }, + "representatives_country_by_weight": { + "title": "البلد" + }, + "representatives_offline": { + "account": "حساب غير متصل", + "last_online": "آخر ظهور على الإنترنت" + }, + "representatives_page": { + "seo_description": "استكشاف وتحليل ممثلي شبكة نانو", + "seo_title": "مستكشف ممثلي نانو", + "telemetry_tab": "القياس عن بعد", + "weight_distribution_tab": "توزيع الوزن", + "weight_history_tab": "تاريخ الوزن", + "offline_reps_tab": "ممثلون غير متصلين" + }, + "representatives_provider_by_weight": { + "title": "مزود الاستضافة" + }, + "representatives_quorum_charts": { + "peers_weight": "وزن الأقران", + "quorum_delta": "فارق النصاب", + "title": "رسومات النصاب", + "trended_weight": "الوزن المتجه" + }, + "representatives_search": { + "placeholder": "تصفية حسب الحساب، الاسم المستعار، الآي بي" + }, + "representatives_weight": { + "trended": "متجه" + }, + "representatives_weight_chart": { + "title": "توزيع الوزن حسب الممثل" + }, + "representatives_version_by_weight": { + "title": "الإصدارات" + }, + "roadmap": { + "header": { + "subtitle": "أهداف المجتمع", + "title": "التخطيط" + }, + "seo": { + "description": "خارطة طريق تطوير ومجتمع نانو", + "tags": [ + "خارطة الطريق", + "نانو", + "المستقبل", + "الإصدار", + "التصميم", + "المهام", + "المناقشات", + "المجتمع", + "السفراء", + "المديرون" + ], + "title": "خارطة الطريق" + } + }, + "search_bar": { + "placeholder": "البحث بواسطة العنوان / هاش الكتلة" + }, + "uptime": { + "now": "الآن", + "days_ago": "أيام مضت" + } +} diff --git a/locales/de.json b/locales/de.json new file mode 100644 index 00000000..89bf3494 --- /dev/null +++ b/locales/de.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Kontoadresse", + "change_summary": "Zusammenfassung ändern", + "copy_notification": "Kontoadresse kopiert", + "seo_description": "Informationen für Nano-Vertreter", + "seo_title": "Nano-Konto", + "telemetry_charts": "Telemetrie-Diagramme", + "unopened_description": "Obwohl die Kontoadresse gültig ist, wurden noch keine Blöcke beobachtet. Wenn NANO an dieses Konto gesendet wurde, muss noch ein entsprechender Block veröffentlicht werden, um die Mittel zu erhalten und ein Eröffnungsguthaben zu erstellen. Das Guthaben eines Kontos kann nur vom Kontoinhaber aktualisiert werden, da nur diese Blöcke in ihrer Kette veröffentlichen können.", + "unopened_note": "Wenn ein Eröffnungsblock bereits veröffentlicht wurde, kann es einige Momente dauern, bis er sich im Netzwerk verbreitet und von den Nano.community-Knoten beobachtet wird.", + "unopened_title": "Dieses Konto wurde noch nicht eröffnet" + }, + "account_blocks_summary": { + "first_timestamp": "Erster Zeitstempel", + "last_timestamp": "Letzter Zeitstempel", + "max_amount": "Maximalbetrag", + "min_amount": "Minimalbetrag", + "no_records": "Keine Aufzeichnungen", + "receiving_account": "Empfangskonto", + "representative_account": "Vertreterkonto", + "sending_account": "Absenderkonto", + "showing_top_10": "Zeigt die Top 10 Konten nach Gesamtbetrag absteigend", + "transactions": "Transaktionen" + }, + "account_meta": { + "account_info": "Kontoinformationen", + "funding_account": "Finanzierungskonto", + "funding_timestamp": "Finanzierungszeitstempel", + "height": "Höhe", + "last_modified": "Zuletzt geändert", + "open_timestamp": "Öffnungszeitstempel", + "opening_balance": "Eröffnungsbilanz", + "receivable_balance": "Forderungssaldo" + }, + "block_page": { + "amount": "Betrag", + "copy_notification": "Blockhash kopiert", + "delegated_representative": "Delegierter Vertreter", + "description": "Beschreibung", + "epoch_v1": "Epoche v1 — Aktualisierte Kontoketten von Legacy-Blöcken (öffnen, empfangen, senden, ändern) zu State-Blöcken.", + "epoch_v2": "Epoche v2 - Aktualisierte Kontoketten für höhere Proof-of-Work-Schwierigkeit.", + "receiving_account": "Empfangskonto", + "section_label": "Blockhash", + "sending_account": "Absenderkonto", + "seo_description": "Informationen zu einem Nano-Block", + "seo_title": "Nano-Block", + "voting_weight": "Stimmengewicht" + }, + "block_info": { + "block_account": "Blockkonto", + "operation": "Operation", + "status": "Status", + "timestamp": "Zeitstempel" + }, + "block_status": { + "confirmed": "Bestätigt", + "unconfirmed": "Unbestätigt" + }, + "block_type": { + "change": "Ändern", + "epoch": "Epoche", + "open": "Öffnen", + "receive": "Empfangen", + "send": "Senden" + }, + "common": { + "account_one": "Konto", + "account_other": "Konten", + "address": "Adresse", + "balance": "Saldo", + "bandwidth_limit": "Bandbreitenlimit", + "bandwidth_limit_short": "BW-Limit", + "blocks": "Blöcke", + "blocks_behind": "Blöcke zurück", + "blocks_diff_short": "Blöcke Diff", + "by_online_weight": "Nach Online-Gewicht", + "clear_filters": "Filter löschen", + "click_to_copy": "Zum Kopieren klicken", + "collapse": "Einklappen", + "conf_short": "Bestät.", + "conf_diff_short": "Bestät. Diff", + "confirmations_behind": "Bestätigungen zurück", + "country": "Land", + "delegator_one": "Delegierender", + "delegator_other": "Delegierende", + "max": "Max", + "min": "Min", + "offline": "Offline", + "online": "Online", + "peers": "Peers", + "percent_of_total": "% des Gesamten", + "port": "Port", + "quorum_delta": "Quorum-Delta", + "representative_one": "Vertreter", + "representative_other": "Vertreter", + "show_more": "Zeige {{count}} mehr", + "total": "Gesamt", + "unchecked": "Ungeprüft", + "unchecked_count": "Ungeprüfte Anzahl", + "unlimited": "Unbegrenzt", + "uptime": "Betriebszeit", + "version": "Version", + "weight": "Gewicht" + }, + "delegators": { + "showing_top_delegators": "Zeigt die Top 100 Delegierenden mit einem Mindestguthaben von 1 Nano." + }, + "doc": { + "contributors": "Mitwirkende", + "document_not_found": "Dokument (oder Konto) nicht gefunden", + "edit_page": "Seite bearbeiten", + "help_out": "Helfen", + "not_found_404": "404", + "section_link_copied": "Abschnittslink kopiert", + "updated_by": "aktualisiert von" + }, + "github_events": { + "action": { + "added_member": "Mitglied hinzugefügt", + "commented_on_commit": "kommentierte Commit", + "commented_on_issue": "kommentierte Problem", + "commented_on_pr_review": "kommentierte PR-Überprüfung", + "created": "erstellt {{action}}", + "deleted": "gelöscht {{action}}", + "forked": "geforkt", + "issue_action": "{{action}} Problem", + "made_public": "öffentlich gemacht", + "pr_action": "{{action}} PR", + "pr_review": "PR-Überprüfung {{title}}", + "published_release": "Veröffentlichung veröffentlicht", + "pushed_commit": "Commit gepusht zu {{ref}}", + "sponsorship_started": "Sponsoring begonnen", + "watching_repo": "beobachtet Repo" + }, + "events_title": "Entwicklungsereignisse" + }, + "ledger": { + "addresses": { + "active_detail": "Aktiv zeigt die Anzahl der einzigartigen Adressen, die verwendet wurden. Neu zeigt die Anzahl der erstellten Adressen. Wiederverwendet zeigt die Anzahl der Adressen, die verwendet wurden, die an einem früheren Tag erstellt wurden.", + "active_stats": "Aktive Adressstatistiken", + "new_stats": "Neue Adressstatistiken", + "total_number": "Die Gesamtzahl der pro Tag verwendeten aktiven, neuen und wiederverwendeten Adressen." + }, + "amounts": { + "total_number": "Die Anzahl der pro Tag bestätigten Sendetyp-Blöcke, bei denen der Betrag im Block in einem bestimmten Bereich liegt (in Nano)" + }, + "blocks": { + "change": "Änderungsblockstatistiken", + "description": "Die Anzahl der pro Tag bestätigten Blöcke.", + "open": "Öffnungsblockstatistiken", + "receive": "Empfangsblockstatistiken", + "send": "Sendeblockstatistiken", + "total": "Gesamtblockstatistiken" + }, + "description": "Beschreibung", + "usd_transferred": { + "desc_1": "Der Gesamtbetrag des pro Tag übertragenen Werts (in USD).", + "desc_2": "Basierend auf dem täglichen Schlusskurs von Nano/USD und dem gesamten an diesem Tag übertragenen Nano-Betrag.", + "usd_transferred": "USD übertragen", + "usd_transferred_stats": "USD-Übertragungsstatistiken" + }, + "volume": { + "change_stats": "Änderungsstatistiken", + "description": "Der gesamte gesendete Betrag (in Nano) und der gesamte Betrag des geänderten Abstimmungsgewichts pro Tag.", + "send_stats": "Sendestatistiken" + } + }, + "ledger_page": { + "addresses_tab": "Adressen", + "amounts_tab": "Beträge", + "blocks_tab": "Blöcke", + "seo_description": "On-Chain-Metriken und Analysen des Nano-Ledgers", + "seo_title": "Nano-Ledger-Analyse", + "value_transferred_tab": "Übertragener Wert", + "volume_tab": "Volumen" + }, + "menu": { + "account_setup": "Kontoeinrichtung", + "acquiring": "Erwerben", + "advantages": "Vorteile", + "attack_vectors": "Angriffsvektoren", + "basics": "Grundlagen", + "best_practices": "Beste Praktiken", + "choosing_a_rep": "Einen Vertreter wählen", + "challenges": "Herausforderungen", + "communities": "Gemeinschaften", + "contribution_guide": "Beitragshandbuch", + "design": "Design", + "developer_discussions": "Entwicklerdiskussionen", + "developers": "Entwickler", + "documentation": "Dokumentation", + "faqs": "FAQs", + "get_involved": "Mitmachen", + "get_support": "Unterstützung erhalten", + "getting_started": "Erste Schritte", + "glossary": "Glossar", + "guides": "Anleitungen", + "history": "Geschichte", + "home": "Startseite", + "how_it_works": "Wie es funktioniert", + "integrations": "Integrationen", + "introduction": "Einführung", + "investment_thesis": "Investmentthese", + "learn": "Lernen", + "ledger": "Ledger", + "misconceptions": "Missverständnisse", + "overview": "Übersicht", + "planning": "Planung", + "privacy": "Datenschutz", + "protocol": "Protokoll", + "running_a_node": "Einen Knoten betreiben", + "security": "Sicherheit", + "stats": "Statistiken", + "storing": "Speichern", + "telemetry": "Telemetrie", + "topics": "Themen", + "using": "Verwenden", + "why_it_matters": "Warum es wichtig ist" + }, + "network": { + "backlog_text": "Mediananzahl der Transaktionen, die auf Bestätigung warten $(network.pr_text)", + "censor_text": "Die Mindestanzahl von Vertretern, die benötigt wird, um Transaktionen zu zensieren oder das Netzwerk zu stoppen", + "confirm_text": "Die Mindestanzahl von Vertretern, die benötigt wird, um Transaktionen zu bestätigen", + "confirmations": "Bestätigungen (24h)", + "confirmations_text": "Gesamtanzahl der Transaktionen, die vom Netzwerk in den letzten 24 Stunden bestätigt wurden", + "energy_text": "Geschätzter CPU-Energieverbrauch des Live-Netzwerks der Hauptvertreter basierend auf gesammelten CPU-Modellinformationen. Die Schätzung basiert auf der CPU-TDP, die die durchschnittliche Leistung in Watt ist, die der Prozessor bei Betrieb mit Basisfrequenz mit allen Kernen unter einer vom Hersteller definierten, hochkomplexen Arbeitslast abgibt", + "energy_usage": "Energieverbrauch (TDP) (24h)", + "fee_text": "Das Nano-Netzwerk funktioniert ohne Gebühren", + "nano_ticker": "NanoTicker", + "online_stake": "Online-Stake", + "principal_reps": "Hauptvertreter", + "pr_text": "wie beobachtet über die Hauptvertreter des Netzwerks: abstimmende Knoten mit mehr als 0,1% des online delegierten Abstimmungsgewichts", + "reps_to_censor": "Vertreter zum Zensieren oder Stoppen", + "reps_to_confirm": "Vertreter zur Bestätigung", + "settlement": "Abwicklung (24h)", + "settlement_text": "Gesamtbetrag des Werts, der vom Netzwerk in den letzten 24 Stunden abgewickelt wurde", + "speed_text": "Zeit in Millisekunden für eine Testtransaktion, um bestätigt zu werden", + "stake_text": "Prozentsatz des delegierten Nano-Gewichts, das aktiv an der Abstimmung teilnimmt", + "stats_title": "Netzwerkstatistiken", + "total_reps": "Gesamtvertreter (24h)", + "tx_backlog": "Tx-Rückstand", + "tx_fees": "Tx-Gebühren (24h)", + "tx_speed": "Tx-Geschwindigkeit", + "tx_throughput": "Tx-Durchsatz", + "throughput_text": "Mediananzahl der Transaktionen, die pro Sekunde in der letzten Minute bestätigt wurden $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano Foundation", + "top": "Top", + "trending": "Trend" + }, + "representative_alerts": { + "table_header": { + "behind": "Zurück", + "issue": "Problem", + "last_online": "Zuletzt online", + "percent_online_weight": "% Online-Gewicht", + "representative": "Vertreter" + }, + "tooltip": { + "behind": "Vertreter ist zurückgefallen oder bootet neu. Der Grenzwert ist eine zementierte Anzahl über dem 95. Perzentil. (via Telemetrie)", + "low_uptime": "Vertreter war mehr als 25% in den letzten 28 Tagen offline.", + "offline": "Vertreter hat aufgehört zu voten und scheint offline zu sein.", + "overweight": "Vertreter hat über 3M Nano Abstimmungsgewicht. Delegierende sollten in Erwägung ziehen, das Gewicht zu verteilen, um die Widerstandsfähigkeit und den Wert des Netzwerks zu verbessern." + }, + "type": { + "behind": "Zurück", + "low_uptime": "Niedrige Betriebszeit", + "offline": "Offline", + "overweight": "Übergewicht" + } + }, + "representatives_cemented_by_weight": { + "title": "Bestätigungsdifferenz", + "tooltip": "Zeigt das Abstimmungsgewicht, das innerhalb einer bestimmten Anzahl von Bestätigungen vom führenden Knoten entfernt ist. Hilfreich, um zu wissen, wie gut synchronisiert und ausgerichtet die Knoten im Netzwerk sind" + }, + "representatives_checked_by_weight": { + "title": "Blockdifferenz", + "tooltip": "Zeigt das Abstimmungsgewicht, das innerhalb einer bestimmten Anzahl von Blöcken vom führenden Knoten entfernt ist. Nützlich, um ein Gefühl dafür zu bekommen, wie gut die Blockverbreitung im Netzwerk synchronisiert ist" + }, + "representative_delegators": { + "showing_top_delegators": "Zeigt die Top 100 Delegierenden mit einem Mindestguthaben von 1 Nano." + }, + "representative_info": { + "first_seen": "Erstmals gesehen", + "last_seen": "Zuletzt gesehen", + "weight_represented": "Vertretenes Gewicht" + }, + "representative_network": { + "city": "Stadt", + "isp": "ISP", + "network": "Netzwerk", + "provider": "Anbieter" + }, + "representative_telemetry": { + "telemetry": "Telemetrie", + "telemetry_timestamp": "Telemetrie-Zeitstempel" + }, + "representative_uptime": { + "2m_uptime": "2M Betriebszeit", + "2w_uptime": "2W Betriebszeit", + "3m_uptime": "3M Betriebszeit", + "current_status": "Aktueller Status", + "down": "Unten", + "down_for": "Unten seit", + "operational": "Betriebsbereit", + "up_for": "Oben seit", + "warning": "Warnung" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "CPU Kerne", + "cpu_model": "CPU Modell", + "tdp": "TDP (wH)", + "protocol_version": "Protokoll", + "last_seen": "Zuletzt gesehen", + "host_asn": "Host ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Zeigt das Abstimmungsgewicht basierend auf dem lokal von jedem Knoten festgelegten Bandbreitenlimit" + }, + "representatives_country_by_weight": { + "title": "Land" + }, + "representatives_offline": { + "account": "Offline-Konto", + "last_online": "Zuletzt online" + }, + "representatives_page": { + "seo_description": "Erkunden und analysieren Sie Nano-Netzwerkvertreter", + "seo_title": "Nano-Vertreter-Explorer", + "telemetry_tab": "Telemetrie", + "weight_distribution_tab": "Gewichtsverteilung", + "weight_history_tab": "Gewichtsverlauf", + "offline_reps_tab": "Offline-Reps" + }, + "representatives_provider_by_weight": { + "title": "Hosting-Anbieter" + }, + "representatives_quorum_charts": { + "peers_weight": "Peers-Gewicht", + "quorum_delta": "Quorum-Delta", + "title": "Quorum-Diagramme", + "trended_weight": "Trendgewicht" + }, + "representatives_search": { + "placeholder": "Filtern nach Konto, Alias, IP" + }, + "representatives_weight": { + "trended": "Trend" + }, + "representatives_weight_chart": { + "title": "Gewichtsverteilung nach Vertreter" + }, + "representatives_version_by_weight": { + "title": "Versionen" + }, + "roadmap": { + "header": { + "subtitle": "Gemeinschaftsziele", + "title": "Planung" + }, + "seo": { + "description": "Nano-Entwicklung & Gemeinschafts-Roadmap", + "tags": [ + "roadmap", + "nano", + "zukunft", + "veröffentlichung", + "design", + "aufgaben", + "diskussionen", + "gemeinschaft", + "botschafter", + "manager" + ], + "title": "Roadmap" + } + }, + "search_bar": { + "placeholder": "Suche nach Adresse / Block-Hash" + }, + "uptime": { + "now": "Jetzt", + "days_ago": "Tage her" + } +} diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 00000000..7852ae07 --- /dev/null +++ b/locales/en.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Account Address", + "change_summary": "Change Summary", + "copy_notification": "Account address copied", + "seo_description": "Information for nano representative", + "seo_title": "Nano Account", + "telemetry_charts": "Telemetry Charts", + "unopened_description": "While the account address is valid, no blocks have been observed. If NANO has been sent to this account, it still needs to publish a corresponding block to receive the funds and establish an opening balance. An account's balance can only be updated by the account holder as they are the only ones who can publish blocks to their chain.", + "unopened_note": "If an opening block has already been published, it may take a few moments to spread through the network and be observed by the nano.community nodes.", + "unopened_title": "This account hasn't been opened yet" + }, + "account_blocks_summary": { + "first_timestamp": "First Timestamp", + "last_timestamp": "Last Timestamp", + "max_amount": "Max Amount", + "min_amount": "Min Amount", + "no_records": "No Records", + "receiving_account": "Receiving Account", + "representative_account": "Representative Account", + "sending_account": "Sending Account", + "showing_top_10": "Showing top 10 accounts by total descending", + "transactions": "TXs" + }, + "account_meta": { + "account_info": "Account Info", + "funding_account": "Funding Account", + "funding_timestamp": "Funding Timestamp", + "height": "Height", + "last_modified": "Last Modified", + "open_timestamp": "Open Timestamp", + "opening_balance": "Opening Balance", + "receivable_balance": "Receivable Balance" + }, + "block_page": { + "amount": "Amount", + "copy_notification": "Block hash copied", + "delegated_representative": "Delegated Representative", + "description": "Description", + "epoch_v1": "Epoch v1 — Upgraded account-chains from legacy blocks (open, receive, send, change) to state blocks.", + "epoch_v2": "Epoch v2 - Upgraded account-chains to use higher Proof-of-Work difficulty.", + "receiving_account": "Receiving Account", + "section_label": "Block Hash", + "sending_account": "Sending Account", + "seo_description": "Information related to a Nano Block", + "seo_title": "Nano Block", + "voting_weight": "Voting Weight" + }, + "block_info": { + "block_account": "Block Account", + "operation": "Operation", + "status": "Status", + "timestamp": "Timestamp" + }, + "block_status": { + "confirmed": "Confirmed", + "unconfirmed": "Unconfirmed" + }, + "block_type": { + "change": "Change", + "epoch": "Epoch", + "open": "Open", + "receive": "Receive", + "send": "Send" + }, + "common": { + "account_one": "Account", + "account_other": "Accounts", + "address": "Address", + "balance": "Balance", + "bandwidth_limit": "Bandwidth Limit", + "bandwidth_limit_short": "BW Limit", + "blocks": "Blocks", + "blocks_behind": "Blocks Behind", + "blocks_diff_short": "Blocks Diff", + "by_online_weight": "By Online Weight", + "clear_filters": "Clear Filters", + "click_to_copy": "Click to copy", + "collapse": "Collapse", + "conf_short": "Conf.", + "conf_diff_short": "Conf. Diff", + "confirmations_behind": "Confirmations Behind", + "country": "Country", + "delegator_one": "Delegator", + "delegator_other": "Delegators", + "max": "Max", + "min": "Min", + "offline": "Offline", + "online": "Online", + "peers": "Peers", + "percent_of_total": "% of Total", + "port": "Port", + "quorum_delta": "Quorum Delta", + "representative_one": "Representative", + "representative_other": "Representatives", + "show_more": "Show {{count}} more", + "total": "Total", + "unchecked": "Unchecked", + "unchecked_count": "Unchecked Count", + "unlimited": "Unlimited", + "uptime": "Uptime", + "version": "Version", + "weight": "Weight" + }, + "delegators": { + "showing_top_delegators": "Showing top 100 delegators with a minimum balance of 1 Nano." + }, + "doc": { + "contributors": "Contributor", + "document_not_found": "Document (or Account) not found", + "edit_page": "Edit Page", + "help_out": "Help out", + "not_found_404": "404", + "section_link_copied": "Section link copied", + "updated_by": "updated by" + }, + "github_events": { + "action": { + "added_member": "added member", + "commented_on_commit": "commented on commit", + "commented_on_issue": "commented on issue", + "commented_on_pr_review": "commented on pr review", + "created": "created {{action}}", + "deleted": "deleted {{action}}", + "forked": "forked", + "issue_action": "{{action}} issue", + "made_public": "made public", + "pr_action": "{{action}} pr", + "pr_review": "pr review {{title}}", + "published_release": "published release", + "pushed_commit": "pushed commit to {{ref}}", + "sponsorship_started": "sponsorship started", + "watching_repo": "watching repo" + }, + "events_title": "Development Events" + }, + "ledger": { + "addresses": { + "active_detail": "Active shows the number of unique addresses used. New shows the number of addresses created. Reused shows the number of addresses used that were created on a previous day.", + "active_stats": "Active Address Stats", + "new_stats": "New Address Stats", + "total_number": "The total number of active, new, and reused addresses used per day." + }, + "amounts": { + "total_number": "The number of confirmed send-type blocks per day where the amount in the block is in a given range (in Nano)" + }, + "blocks": { + "change": "Change Block Stats", + "description": "The number of blocks confirmed per day.", + "open": "Open Block Stats", + "receive": "Receive Block Stats", + "send": "Send Block Stats", + "total": "Total Block Stats" + }, + "description": "Description", + "usd_transferred": { + "desc_1": "The total amount of value transferred (in USD) per day.", + "desc_2": "Based on the daily closing price of Nano/USD and the total amount of Nano transferred that day.", + "usd_transferred": "USD Transferred", + "usd_transferred_stats": "USD Transferred Stats" + }, + "volume": { + "change_stats": "Change Stats", + "description": "The total amount sent (in Nano) and total amount of voting weight changed per day.", + "send_stats": "Send Stats" + } + }, + "ledger_page": { + "addresses_tab": "Addresses", + "amounts_tab": "Amounts", + "blocks_tab": "Blocks", + "seo_description": "On-chain metrics and analytics of the Nano ledger", + "seo_title": "Nano Ledger Analysis", + "value_transferred_tab": "Value Transferred", + "volume_tab": "Volume" + }, + "menu": { + "account_setup": "Account Setup", + "acquiring": "Acquiring", + "advantages": "Advantages", + "attack_vectors": "Attack Vectors", + "basics": "Basics", + "best_practices": "Best Practices", + "choosing_a_rep": "Choosing a Rep", + "challenges": "Challenges", + "communities": "Communities", + "contribution_guide": "Contribution Guide", + "design": "Design", + "developer_discussions": "Developer Discussions", + "developers": "Developers", + "documentation": "Documentation", + "faqs": "FAQs", + "get_involved": "Get Involved", + "get_support": "Get Support", + "getting_started": "Getting Started", + "glossary": "Glossary", + "guides": "Guides", + "history": "History", + "home": "Home", + "how_it_works": "How it works", + "integrations": "Integrations", + "introduction": "Introduction", + "investment_thesis": "Investment thesis", + "learn": "Learn", + "ledger": "Ledger", + "misconceptions": "Misconceptions", + "overview": "Overview", + "planning": "Planning 👾", + "privacy": "Privacy", + "protocol": "Protocol", + "running_a_node": "Running a node", + "security": "Security", + "stats": "Stats", + "storing": "Storing", + "telemetry": "Telemetry", + "topics": "Topics", + "using": "Using", + "why_it_matters": "Why it matters" + }, + "network": { + "unconfirmed_pool_text": "Number of blocks waiting to be confirmed $(network.pr_text)", + "censor_text": "The minimum number of representatives needed to censor transactions or stall the network", + "confirm_text": "The minimum number of representatives needed to confirm transactions", + "confirmations": "Confirmations (24h)", + "confirmations_text": "Total number of transactions confirmed by the network over the last 24 hours", + "energy_text": "Estimated live network CPU energy usage of Principle Representatives based on collected CPU model info. The estimate is based on CPU TDP, which is the average power, in watts, the processor dissipates when operating at base frequency with all cores active under manufacture-defined, high-complexity workload", + "energy_usage": "Energy Usage (TDP) (24h)", + "fee_text": "The Nano network operates without fees", + "nano_ticker": "NanoTicker", + "online_stake": "Online Stake", + "principal_reps": "Principal Reps", + "pr_text": "as observed across the networks principal representatives: voting nodes with more than 0.1% of the online voting weight delegated to them", + "reps_to_censor": "Reps to Censor or Stall", + "reps_to_confirm": "Reps to Confirm", + "settlement": "Settlement (24h)", + "settlement_text": "Total amount of value settled by the network over the last 24 hours (only send blocks)", + "speed_text": "Median time in milliseconds for a block to get confirmed (across all buckets)", + "stake_text": "Percentage of delegated Nano weight actively participating in voting", + "stats_title": "Network Stats", + "total_reps": "Total Reps (24h)", + "tx_backlog": "Tx Backlog", + "tx_fees": "Tx Fees (24h)", + "tx_speed": "Tx Speed ({{time_range}})", + "tx_throughput": "Tx Throughput", + "throughput_text": "Median number of transactions confirmed per second in the last minute $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano Foundation", + "top": "Top", + "trending": "Trending" + }, + "representative_alerts": { + "table_header": { + "behind": "Behind", + "issue": "Issue", + "last_online": "Last Online", + "percent_online_weight": "% Online Weight", + "representative": "Representative" + }, + "tooltip": { + "behind": "Representative has fallen behind or is bootstrapping. The cutoff is a cemented count beyond the 95th percentile. (via telemetry)", + "low_uptime": "Representative has been offline more than 25% in the last 28 days.", + "offline": "Representative has stopped voting and appears offline.", + "overweight": "Representative has beyond 3M Nano voting weight. Delegators should consider distributing the weight to improve the network's resilience and value." + }, + "type": { + "behind": "Behind", + "low_uptime": "Low Uptime", + "offline": "Offline", + "overweight": "Overweight" + } + }, + "representatives_cemented_by_weight": { + "title": "Confirmation Differential", + "tooltip": "Displays the amount of voting weight that is within X number of confirmations from the leading node. Helpful in knowing how well in-sync and aligned nodes are across the network" + }, + "representatives_checked_by_weight": { + "title": "Blocks Differential", + "tooltip": "Displays the amount of voting weight that is within X number of blocks from the leading node. Useful for getting a sense of how in-sync block propagation is within the network" + }, + "representative_delegators": { + "showing_top_delegators": "Showing top 100 delegators with a minimum balance of 1 Nano." + }, + "representative_info": { + "first_seen": "First Seen", + "last_seen": "Last Seen", + "weight_represented": "Weight Represented" + }, + "representative_network": { + "city": "City", + "isp": "ISP", + "network": "Network", + "provider": "Provider" + }, + "representative_telemetry": { + "telemetry": "Telemetry", + "telemetry_timestamp": "Telemetry Timestamp" + }, + "representative_uptime": { + "2m_uptime": "2M Uptime", + "2w_uptime": "2W Uptime", + "3m_uptime": "3M Uptime", + "current_status": "Current Status", + "down": "Down", + "down_for": "Down for", + "operational": "Operational", + "up_for": "Up for", + "warning": "Warning" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "CPU Cores", + "cpu_model": "CPU Model", + "tdp": "TDP (wH)", + "protocol_version": "Protocol", + "last_seen": "Last Seen", + "host_asn": "Host ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Displays the amount of voting weight based on the bandwidth limit set locally by each node" + }, + "representatives_country_by_weight": { + "title": "Country" + }, + "representatives_offline": { + "account": "Offline Account", + "last_online": "Last Online" + }, + "representatives_page": { + "seo_description": "Explore and analyze Nano network representatives", + "seo_title": "Nano Representatives Explorer", + "telemetry_tab": "Telemetry", + "weight_distribution_tab": "Weight Distribution", + "weight_history_tab": "Weight History", + "offline_reps_tab": "Offline Reps" + }, + "representatives_provider_by_weight": { + "title": "Hosting Provider" + }, + "representatives_quorum_charts": { + "peers_weight": "Peers Weight", + "quorum_delta": "Quorum Delta", + "title": "Quorum Charts", + "trended_weight": "Trended Weight" + }, + "representatives_search": { + "placeholder": "Filter by account, alias, ip" + }, + "representatives_weight": { + "trended": "Trended" + }, + "representatives_weight_chart": { + "title": "Weight Distribution by Representative" + }, + "representatives_version_by_weight": { + "title": "Versions" + }, + "roadmap": { + "header": { + "subtitle": "Community objectives", + "title": "Planning" + }, + "seo": { + "description": "Nano development & community roadmap", + "tags": [ + "roadmap", + "nano", + "future", + "release", + "design", + "tasks", + "discussions", + "community", + "ambassadors", + "managers" + ], + "title": "Roadmap" + } + }, + "search_bar": { + "placeholder": "Search by Address / Block Hash" + }, + "uptime": { + "now": "Now", + "days_ago": "days ago" + } +} diff --git a/locales/es.json b/locales/es.json new file mode 100644 index 00000000..d6cbf2e2 --- /dev/null +++ b/locales/es.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Dirección de la Cuenta", + "change_summary": "Resumen de Cambios", + "copy_notification": "Dirección de cuenta copiada", + "seo_description": "Información para representante nano", + "seo_title": "Cuenta Nano", + "telemetry_charts": "Gráficos de Telemetría", + "unopened_description": "Aunque la dirección de la cuenta es válida, no se han observado bloques. Si se ha enviado NANO a esta cuenta, aún necesita publicar un bloque correspondiente para recibir los fondos y establecer un saldo inicial. El saldo de una cuenta solo puede ser actualizado por el titular de la cuenta ya que son los únicos que pueden publicar bloques en su cadena.", + "unopened_note": "Si ya se ha publicado un bloque de apertura, puede tardar unos momentos en propagarse por la red y ser observado por los nodos de nano.community.", + "unopened_title": "Esta cuenta no ha sido abierta aún" + }, + "account_blocks_summary": { + "first_timestamp": "Primera Marca de Tiempo", + "last_timestamp": "Última Marca de Tiempo", + "max_amount": "Cantidad Máxima", + "min_amount": "Cantidad Mínima", + "no_records": "Sin Registros", + "receiving_account": "Cuenta Receptora", + "representative_account": "Cuenta Representativa", + "sending_account": "Cuenta Emisora", + "showing_top_10": "Mostrando las 10 mejores cuentas por total descendente", + "transactions": "TXs" + }, + "account_meta": { + "account_info": "Información de la Cuenta", + "funding_account": "Cuenta de Financiación", + "funding_timestamp": "Marca de Tiempo de Financiación", + "height": "Altura", + "last_modified": "Última Modificación", + "open_timestamp": "Marca de Tiempo de Apertura", + "opening_balance": "Saldo de Apertura", + "receivable_balance": "Saldo por Cobrar" + }, + "block_page": { + "amount": "Cantidad", + "copy_notification": "Hash de bloque copiado", + "delegated_representative": "Representante Delegado", + "description": "Descripción", + "epoch_v1": "Época v1 — Cadenas de cuentas actualizadas de bloques heredados (abrir, recibir, enviar, cambiar) a bloques de estado.", + "epoch_v2": "Época v2 - Cadenas de cuentas actualizadas para usar una dificultad de Prueba de Trabajo más alta.", + "receiving_account": "Cuenta Receptora", + "section_label": "Hash de Bloque", + "sending_account": "Cuenta Emisora", + "seo_description": "Información relacionada con un Bloque Nano", + "seo_title": "Bloque Nano", + "voting_weight": "Peso de Votación" + }, + "block_info": { + "block_account": "Cuenta de Bloque", + "operation": "Operación", + "status": "Estado", + "timestamp": "Marca de Tiempo" + }, + "block_status": { + "confirmed": "Confirmado", + "unconfirmed": "No Confirmado" + }, + "block_type": { + "change": "Cambiar", + "epoch": "Época", + "open": "Abrir", + "receive": "Recibir", + "send": "Enviar" + }, + "common": { + "account_one": "Cuenta", + "account_other": "Cuentas", + "address": "Dirección", + "balance": "Saldo", + "bandwidth_limit": "Límite de Ancho de Banda", + "bandwidth_limit_short": "Límite de BW", + "blocks": "Bloques", + "blocks_behind": "Bloques Atrasados", + "blocks_diff_short": "Dif de Bloques", + "by_online_weight": "Por Peso en Línea", + "clear_filters": "Limpiar Filtros", + "click_to_copy": "Clic para copiar", + "collapse": "Colapsar", + "conf_diff_short": "Dif de Conf", + "conf_short": "Conf.", + "confirmations_behind": "Confirmaciones Atrasadas", + "country": "País", + "delegator_one": "Delegador", + "delegator_other": "Delegadores", + "max": "Máx", + "min": "Mín", + "offline": "Fuera de Línea", + "online": "En Línea", + "peers": "Pares", + "percent_of_total": "% del Total", + "port": "Puerto", + "quorum_delta": "Delta de Cuórum", + "representative_one": "Representante", + "representative_other": "Representantes", + "show_more": "Mostrar {{count}} más", + "total": "Total", + "unchecked": "Sin Verificar", + "unchecked_count": "Cuenta Sin Verificar", + "unlimited": "Ilimitado", + "uptime": "Tiempo Activo", + "version": "Versión", + "weight": "Peso" + }, + "delegators": { + "showing_top_delegators": "Mostrando los 100 principales delegadores con un saldo mínimo de 1 Nano." + }, + "doc": { + "contributors": "Colaborador", + "document_not_found": "Documento (o Cuenta) no encontrado", + "edit_page": "Editar Página", + "help_out": "Ayudar", + "not_found_404": "404", + "section_link_copied": "Enlace de sección copiado", + "updated_by": "actualizado por" + }, + "github_events": { + "action": { + "added_member": "miembro agregado", + "commented_on_commit": "comentó en commit", + "commented_on_issue": "comentó en problema", + "commented_on_pr_review": "comentó en revisión de pr", + "created": "creado {{action}}", + "deleted": "eliminado {{action}}", + "forked": "bifurcado", + "issue_action": "{{action}} problema", + "made_public": "hecho público", + "pr_action": "{{action}} pr", + "pr_review": "revisión de pr {{title}}", + "published_release": "lanzamiento publicado", + "pushed_commit": "commit empujado a {{ref}}", + "sponsorship_started": "patrocinio iniciado", + "watching_repo": "observando repositorio" + }, + "events_title": "Eventos de Desarrollo" + }, + "ledger": { + "addresses": { + "active_detail": "Activo muestra el número de direcciones únicas utilizadas. Nuevo muestra el número de direcciones creadas. Reutilizado muestra el número de direcciones utilizadas que fueron creadas en un día anterior.", + "active_stats": "Estadísticas de Direcciones Activas", + "new_stats": "Estadísticas de Nuevas Direcciones", + "total_number": "El número total de direcciones activas, nuevas y reutilizadas utilizadas por día." + }, + "amounts": { + "total_number": "El número de bloques de tipo envío confirmados por día donde la cantidad en el bloque está en un rango dado (en Nano)" + }, + "blocks": { + "change": "Estadísticas de Bloques de Cambio", + "description": "El número de bloques confirmados por día.", + "open": "Estadísticas de Bloques de Apertura", + "receive": "Estadísticas de Bloques de Recepción", + "send": "Estadísticas de Bloques de Envío", + "total": "Estadísticas de Bloques Totales" + }, + "description": "Descripción", + "usd_transferred": { + "desc_1": "El monto total de valor transferido (en USD) por día.", + "desc_2": "Basado en el precio de cierre diario de Nano/USD y el monto total de Nano transferido ese día.", + "usd_transferred": "USD Transferidos", + "usd_transferred_stats": "Estadísticas de USD Transferidos" + }, + "volume": { + "change_stats": "Estadísticas de Cambio", + "description": "El monto total enviado (en Nano) y el monto total de peso de votación cambiado por día.", + "send_stats": "Estadísticas de Envío" + } + }, + "ledger_page": { + "addresses_tab": "Direcciones", + "amounts_tab": "Cantidades", + "blocks_tab": "Bloques", + "seo_description": "Métricas y análisis en cadena del libro mayor de Nano", + "seo_title": "Análisis del Libro Mayor de Nano", + "value_transferred_tab": "Valor Transferido", + "volume_tab": "Volumen" + }, + "menu": { + "account_setup": "Configuración de la Cuenta", + "acquiring": "Adquiriendo", + "advantages": "Ventajas", + "attack_vectors": "Vectores de Ataque", + "basics": "Básicos", + "best_practices": "Mejores Prácticas", + "choosing_a_rep": "Elegir un Representante", + "challenges": "Desafíos", + "communities": "Comunidades", + "contribution_guide": "Guía de Contribución", + "design": "Diseño", + "developer_discussions": "Discusiones de Desarrolladores", + "developers": "Desarrolladores", + "documentation": "Documentación", + "faqs": "Preguntas Frecuentes", + "get_involved": "Involúcrate", + "get_support": "Obtener Soporte", + "getting_started": "Empezando", + "glossary": "Glosario", + "guides": "Guías", + "history": "Historia", + "home": "Inicio", + "how_it_works": "Cómo Funciona", + "integrations": "Integraciones", + "introduction": "Introducción", + "investment_thesis": "Tesis de Inversión", + "learn": "Aprender", + "ledger": "Libro Mayor", + "misconceptions": "Malentendidos", + "overview": "Visión General", + "planning": "Planificación 👾", + "privacy": "Privacidad", + "protocol": "Protocolo", + "running_a_node": "Ejecutando un Nodo", + "security": "Seguridad", + "stats": "Estadísticas", + "storing": "Almacenando", + "telemetry": "Telemetría", + "topics": "Temas", + "using": "Usando", + "why_it_matters": "Por Qué es Importante" + }, + "network": { + "backlog_text": "Número mediano de transacciones esperando ser confirmadas $(network.pr_text)", + "censor_text": "El número mínimo de representantes necesarios para censurar transacciones o paralizar la red", + "confirm_text": "El número mínimo de representantes necesarios para confirmar transacciones", + "confirmations": "Confirmaciones (24h)", + "confirmations_text": "Número total de transacciones confirmadas por la red en las últimas 24 horas", + "energy_text": "Estimación del uso de energía de CPU de la red en vivo de los Representantes Principales basada en la información recopilada del modelo de CPU. La estimación se basa en el TDP de la CPU, que es la potencia promedio, en vatios, que disipa el procesador cuando opera a la frecuencia base con todos los núcleos activos bajo una carga de trabajo de alta complejidad definida por el fabricante", + "energy_usage": "Uso de Energía (TDP) (24h)", + "fee_text": "La red Nano opera sin tarifas", + "nano_ticker": "NanoTicker", + "online_stake": "Participación en Línea", + "principal_reps": "Representantes Principales", + "pr_text": "según se observa en los representantes principales de la red: nodos de votación con más del 0.1% del peso de voto en línea delegado a ellos", + "reps_to_censor": "Representantes para Censurar o Paralizar", + "reps_to_confirm": "Representantes para Confirmar", + "settlement": "Liquidación (24h)", + "settlement_text": "Cantidad total de valor liquidado por la red en las últimas 24 horas", + "speed_text": "Tiempo en milisegundos para que una transacción de prueba sea confirmada", + "stake_text": "Porcentaje del peso Nano delegado que participa activamente en la votación", + "stats_title": "Estadísticas de la Red", + "total_reps": "Total de Representantes (24h)", + "tx_backlog": "Cola de Tx", + "tx_fees": "Tarifas de Tx (24h)", + "tx_speed": "Velocidad de Tx", + "tx_throughput": "Rendimiento de Tx", + "throughput_text": "Número mediano de transacciones confirmadas por segundo en el último minuto $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Fundación Nano", + "top": "Top", + "trending": "Tendencias" + }, + "representative_alerts": { + "table_header": { + "behind": "Atrasado", + "issue": "Problema", + "last_online": "Última vez en línea", + "percent_online_weight": "% Peso en Línea", + "representative": "Representante" + }, + "tooltip": { + "behind": "El representante se ha quedado atrás o está arrancando. El límite es un recuento cementado más allá del percentil 95. (vía telemetría)", + "low_uptime": "El representante ha estado fuera de línea más del 25% en los últimos 28 días.", + "offline": "El representante ha dejado de votar y parece estar fuera de línea.", + "overweight": "El representante tiene más de 3M de peso de voto Nano. Los delegadores deberían considerar distribuir el peso para mejorar la resiliencia de la red y su valor." + }, + "type": { + "behind": "Atrasado", + "low_uptime": "Bajo Tiempo Activo", + "offline": "Fuera de Línea", + "overweight": "Sobrepeso" + } + }, + "representatives_cemented_by_weight": { + "title": "Diferencial de Confirmación", + "tooltip": "Muestra la cantidad de peso de voto que está dentro de X número de confirmaciones del nodo líder. Útil para saber qué tan bien sincronizados y alineados están los nodos a través de la red" + }, + "representatives_checked_by_weight": { + "title": "Diferencial de Bloques", + "tooltip": "Muestra la cantidad de peso de voto que está dentro de X número de bloques del nodo líder. Útil para tener una idea de qué tan bien se propaga la sincronización de bloques dentro de la red" + }, + "representative_delegators": { + "showing_top_delegators": "Mostrando los 100 principales delegadores con un saldo mínimo de 1 Nano." + }, + "representative_info": { + "first_seen": "Primera Vez Visto", + "last_seen": "Última Vez Visto", + "weight_represented": "Peso Representado" + }, + "representative_network": { + "city": "Ciudad", + "isp": "ISP", + "network": "Red", + "provider": "Proveedor" + }, + "representative_telemetry": { + "telemetry": "Telemetría", + "telemetry_timestamp": "Marca de Tiempo de Telemetría" + }, + "representative_uptime": { + "2m_uptime": "Tiempo Activo 2M", + "2w_uptime": "Tiempo Activo 2S", + "3m_uptime": "Tiempo Activo 3M", + "current_status": "Estado Actual", + "down": "Caído", + "down_for": "Caído Durante", + "operational": "Operativo", + "up_for": "Activo Durante", + "warning": "Advertencia" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "Núcleos de CPU", + "cpu_model": "Modelo de CPU", + "tdp": "TDP (wH)", + "protocol_version": "Versión del Protocolo", + "last_seen": "Última Vez Visto", + "host_asn": "ASN del Host" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Muestra la cantidad de peso de voto basado en el límite de ancho de banda establecido localmente por cada nodo" + }, + "representatives_country_by_weight": { + "title": "País" + }, + "representatives_offline": { + "account": "Cuenta Fuera de Línea", + "last_online": "Última Vez en Línea" + }, + "representatives_page": { + "seo_description": "Explora y analiza los representantes de la red Nano", + "seo_title": "Explorador de Representantes Nano", + "telemetry_tab": "Telemetría", + "weight_distribution_tab": "Distribución del Peso", + "weight_history_tab": "Historial del Peso", + "offline_reps_tab": "Representantes Fuera de Línea" + }, + "representatives_provider_by_weight": { + "title": "Proveedor de Hosting" + }, + "representatives_quorum_charts": { + "peers_weight": "Peso de los Pares", + "quorum_delta": "Delta del Cuórum", + "title": "Gráficos del Cuórum", + "trended_weight": "Peso Tendencial" + }, + "representatives_search": { + "placeholder": "Filtrar por cuenta, alias, ip" + }, + "representatives_weight": { + "trended": "Tendencial" + }, + "representatives_weight_chart": { + "title": "Distribución del Peso por Representante" + }, + "representatives_version_by_weight": { + "title": "Versiones" + }, + "roadmap": { + "header": { + "subtitle": "Objetivos de la comunidad", + "title": "Planificación" + }, + "seo": { + "description": "Hoja de ruta de desarrollo y comunidad de Nano", + "tags": [ + "hoja de ruta", + "nano", + "futuro", + "lanzamiento", + "diseño", + "tareas", + "discusiones", + "comunidad", + "embajadores", + "gestores" + ], + "title": "Hoja de Ruta" + } + }, + "search_bar": { + "placeholder": "Buscar por Dirección / Hash de Bloque" + }, + "uptime": { + "now": "Ahora", + "days_ago": "días atrás" + } +} diff --git a/locales/fa.json b/locales/fa.json new file mode 100644 index 00000000..f9a8b8dc --- /dev/null +++ b/locales/fa.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "آدرس حساب", + "change_summary": "خلاصه تغییرات", + "copy_notification": "آدرس حساب کپی شد", + "seo_description": "اطلاعاتی برای نماینده نانو", + "seo_title": "حساب نانو", + "telemetry_charts": "نمودارهای تلمتری", + "unopened_description": "در حالی که آدرس حساب معتبر است، هیچ بلوکی مشاهده نشده است. اگر نانو به این حساب ارسال شده باشد، هنوز باید یک بلوک متناظر برای دریافت وجوه و ایجاد یک موجودی افتتاحیه منتشر کند. تنها دارنده حساب می‌تواند موجودی حساب را به‌روزرسانی کند زیرا تنها آن‌ها می‌توانند بلوک‌ها را به زنجیره خود انتشار دهند.", + "unopened_note": "اگر یک بلوک افتتاحیه قبلاً منتشر شده باشد، ممکن است چند لحظه طول بکشد تا از طریق شبکه پخش شود و توسط گره‌های nano.community مشاهده شود.", + "unopened_title": "این حساب هنوز باز نشده است" + }, + "account_blocks_summary": { + "first_timestamp": "اولین زمان‌بندی", + "last_timestamp": "آخرین زمان‌بندی", + "max_amount": "حداکثر مقدار", + "min_amount": "حداقل مقدار", + "no_records": "بدون سابقه", + "receiving_account": "حساب دریافتی", + "representative_account": "حساب نماینده", + "sending_account": "حساب ارسالی", + "showing_top_10": "نمایش ۱۰ حساب برتر بر اساس کل نزولی", + "transactions": "تراکنش‌ها" + }, + "account_meta": { + "account_info": "اطلاعات حساب", + "funding_account": "حساب تأمین مالی", + "funding_timestamp": "زمان‌بندی تأمین مالی", + "height": "ارتفاع", + "last_modified": "آخرین تغییر", + "open_timestamp": "زمان‌بندی باز", + "opening_balance": "موجودی افتتاحیه", + "receivable_balance": "موجودی قابل دریافت" + }, + "block_page": { + "amount": "مقدار", + "copy_notification": "هش بلوک کپی شد", + "delegated_representative": "نماینده تفویضی", + "description": "توضیحات", + "epoch_v1": "عصر v1 - زنجیره‌های حساب از بلوک‌های قدیمی (باز، دریافت، ارسال، تغییر) به بلوک‌های حالت ارتقا یافتند.", + "epoch_v2": "عصر v2 - ارتقاء زنجیره‌های حساب برای استفاده از سختی بیشتر Proof-of-Work.", + "receiving_account": "حساب دریافتی", + "section_label": "هش بلوک", + "sending_account": "حساب ارسالی", + "seo_description": "اطلاعات مرتبط با یک بلوک نانو", + "seo_title": "بلوک نانو", + "voting_weight": "وزن رأی" + }, + "block_info": { + "block_account": "حساب بلوک", + "operation": "عملیات", + "status": "وضعیت", + "timestamp": "زمان‌بندی" + }, + "block_status": { + "confirmed": "تایید شده", + "unconfirmed": "تایید نشده" + }, + "block_type": { + "change": "تغییر", + "epoch": "عصر", + "open": "باز", + "receive": "دریافت", + "send": "ارسال" + }, + "common": { + "account_one": "حساب", + "account_other": "حساب‌ها", + "address": "آدرس", + "balance": "موجودی", + "bandwidth_limit": "محدودیت پهنای باند", + "bandwidth_limit_short": "محدودیت پهنای باند", + "blocks": "بلوک‌ها", + "blocks_behind": "بلوک‌های عقب", + "blocks_diff_short": "تفاوت بلوک‌ها", + "by_online_weight": "بر اساس وزن آنلاین", + "clear_filters": "پاک کردن فیلترها", + "click_to_copy": "برای کپی کلیک کنید", + "collapse": "بستن", + "conf_short": "تایید.", + "conf_diff_short": "تفاوت تایید", + "confirmations_behind": "تاییدیه‌های عقب", + "country": "کشور", + "delegator_one": "واگذار کننده", + "delegator_other": "واگذار کنندگان", + "max": "حداکثر", + "min": "حداقل", + "offline": "آفلاین", + "online": "آنلاین", + "peers": "همتاها", + "percent_of_total": "% از کل", + "port": "پورت", + "quorum_delta": "اختلاف کوروم", + "representative_one": "نماینده", + "representative_other": "نمایندگان", + "show_more": "نمایش {{count}} بیشتر", + "total": "کل", + "unchecked": "بررسی نشده", + "unchecked_count": "تعداد بررسی نشده", + "unlimited": "نامحدود", + "uptime": "زمان کارکرد", + "version": "نسخه", + "weight": "وزن" + }, + "delegators": { + "showing_top_delegators": "نمایش ۱۰۰ واگذار کننده برتر با حداقل موجودی ۱ نانو." + }, + "doc": { + "contributors": "مشارکت کنندگان", + "document_not_found": "سند (یا حساب) یافت نشد", + "edit_page": "ویرایش صفحه", + "help_out": "کمک کنید", + "not_found_404": "۴۰۴", + "section_link_copied": "لینک بخش کپی شد", + "updated_by": "به‌روزرسانی شده توسط" + }, + "github_events": { + "action": { + "added_member": "عضو اضافه شد", + "commented_on_commit": "نظر داده شده روی کامیت", + "commented_on_issue": "نظر داده شده روی مسئله", + "commented_on_pr_review": "نظر داده شده روی بازبینی PR", + "created": "ایجاد شده {{action}}", + "deleted": "حذف شده {{action}}", + "forked": "فورک شده", + "issue_action": "{{action}} مسئله", + "made_public": "عمومی شد", + "pr_action": "{{action}} pr", + "pr_review": "بررسی pr {{title}}", + "published_release": "انتشار منتشر شده", + "pushed_commit": "کامیت فشرده به {{ref}}", + "sponsorship_started": "حمایت شروع شد", + "watching_repo": "دنبال کردن مخزن" + }, + "events_title": "رویدادهای توسعه" + }, + "ledger": { + "addresses": { + "active_detail": "فعال نشان دهنده تعداد آدرس‌های منحصر به فرد استفاده شده است. جدید نشان دهنده تعداد آدرس‌های ایجاد شده است. استفاده مجدد نشان دهنده تعداد آدرس‌های استفاده شده که در روز قبل ایجاد شده‌اند.", + "active_stats": "آمار آدرس‌های فعال", + "new_stats": "آمار آدرس‌های جدید", + "total_number": "تعداد کل آدرس‌های فعال، جدید و استفاده مجدد به ازای هر روز." + }, + "amounts": { + "total_number": "تعداد بلوک‌های تایید شده از نوع ارسال در هر روز که مقدار در بلوک در یک محدوده معین (به نانو) است" + }, + "blocks": { + "change": "آمار بلوک تغییر", + "description": "تعداد بلوک‌های تایید شده در هر روز.", + "open": "آمار بلوک باز", + "receive": "آمار بلوک دریافتی", + "send": "آمار بلوک ارسالی", + "total": "آمار کل بلوک" + }, + "description": "توضیحات", + "usd_transferred": { + "desc_1": "مجموع مقدار ارزش انتقال یافته (به دلار آمریکا) به ازای هر روز.", + "desc_2": "بر اساس قیمت پایانی روزانه نانو/دلار آمریکا و مجموع مقدار نانو انتقال یافته در آن روز.", + "usd_transferred": "دلار انتقال یافته", + "usd_transferred_stats": "آمار دلار انتقال یافته" + }, + "volume": { + "change_stats": "آمار تغییر", + "description": "مجموع مقدار ارسال شده (به نانو) و مجموع مقدار وزن رای تغییر یافته به ازای هر روز.", + "send_stats": "آمار ارسال" + } + }, + "ledger_page": { + "addresses_tab": "آدرس‌ها", + "amounts_tab": "مقادیر", + "blocks_tab": "بلوک‌ها", + "seo_description": "معیارها و تحلیل‌های زنجیره نانو", + "seo_title": "تحلیل زنجیره نانو", + "value_transferred_tab": "ارزش انتقالی", + "volume_tab": "حجم" + }, + "menu": { + "account_setup": "راه‌اندازی حساب", + "acquiring": "کسب", + "advantages": "مزایا", + "attack_vectors": "بردارهای حمله", + "basics": "مبانی", + "best_practices": "بهترین شیوه‌ها", + "choosing_a_rep": "انتخاب نماینده", + "challenges": "چالش‌ها", + "communities": "جوامع", + "contribution_guide": "راهنمای مشارکت", + "design": "طراحی", + "developer_discussions": "بحث‌های توسعه‌دهندگان", + "developers": "توسعه‌دهندگان", + "documentation": "مستندات", + "faqs": "سوالات متداول", + "get_involved": "مشارکت کنید", + "get_support": "پشتیبانی دریافت کنید", + "getting_started": "شروع کار", + "glossary": "واژه‌نامه", + "guides": "راهنماها", + "history": "تاریخچه", + "home": "خانه", + "how_it_works": "چگونه کار می‌کند", + "integrations": "یکپارچه‌سازی‌ها", + "introduction": "مقدمه", + "investment_thesis": "پایان‌نامه سرمایه‌گذاری", + "learn": "یادگیری", + "ledger": "دفتر کل", + "misconceptions": "تصورات غلط", + "overview": "بررسی اجمالی", + "planning": "برنامه‌ریزی 👾", + "privacy": "حریم خصوصی", + "protocol": "پروتکل", + "running_a_node": "اجرای یک گره", + "security": "امنیت", + "stats": "آمار", + "storing": "ذخیره‌سازی", + "telemetry": "داده‌نمایی", + "topics": "موضوعات", + "using": "استفاده", + "why_it_matters": "چرا مهم است" + }, + "network": { + "backlog_text": "تعداد میانی تراکنش‌های در انتظار تایید $(network.pr_text)", + "censor_text": "حداقل تعداد نمایندگان مورد نیاز برای سانسور تراکنش‌ها یا توقف شبکه", + "confirm_text": "حداقل تعداد نمایندگان مورد نیاز برای تایید تراکنش‌ها", + "confirmations": "تاییدیه‌ها (24 ساعت)", + "confirmations_text": "تعداد کل تراکنش‌های تایید شده توسط شبکه در 24 ساعت گذشته", + "energy_text": "مصرف انرژی CPU شبکه زنده برآورد شده از نمایندگان اصلی بر اساس اطلاعات مدل CPU جمع‌آوری شده. این برآورد بر اساس TDP CPU است که میانگین قدرت، به وات، پردازنده است که هنگام کار در فرکانس پایه با همه هسته‌ها فعال تحت بار کاری پیچیده تعریف شده توسط تولید، پراکنده می‌شود", + "energy_usage": "مصرف انرژی (TDP) (24 ساعت)", + "fee_text": "شبکه نانو بدون هزینه عمل می‌کند", + "nano_ticker": "نانو تیکر", + "online_stake": "سهم آنلاین", + "principal_reps": "نمایندگان اصلی", + "pr_text": "همانطور که در نمایندگان اصلی شبکه مشاهده می‌شود: گره‌های رای‌دهی با بیش از 0.1٪ از وزن رای آنلاین به آنها تفویض شده است", + "reps_to_censor": "نمایندگان برای سانسور یا توقف", + "reps_to_confirm": "نمایندگان برای تایید", + "settlement": "تسویه (24 ساعت)", + "settlement_text": "مجموع مقدار ارزش تسویه شده توسط شبکه در 24 ساعت گذشته", + "speed_text": "زمان به میلی‌ثانیه برای تایید یک تراکنش آزمایشی", + "stake_text": "درصد وزن نانو تفویض شده که در رای‌گیری فعالانه شرکت می‌کند", + "stats_title": "آمار شبکه", + "total_reps": "کل نمایندگان (24 ساعت)", + "tx_backlog": "تراکنش‌های معوق", + "tx_fees": "هزینه‌های تراکنش (24 ساعت)", + "tx_speed": "سرعت تراکنش", + "tx_throughput": "ظرفیت تراکنش", + "throughput_text": "تعداد میانی تراکنش‌های تایید شده در هر ثانیه در دقیقه گذشته $(network.pr_text)" + }, + "posts": { + "nano_foundation": "بنیاد نانو", + "top": "بالا", + "trending": "در حال ترند" + }, + "representative_alerts": { + "table_header": { + "behind": "عقب", + "issue": "مشکل", + "last_online": "آخرین آنلاین", + "percent_online_weight": "% وزن آنلاین", + "representative": "نماینده" + }, + "tooltip": { + "behind": "نماینده عقب افتاده یا در حال بوت‌استرپ است. حد برش تعداد سیمانی فراتر از نود و پنجمین درصدیل است. (از طریق تلمتری)", + "low_uptime": "نماینده بیش از 25٪ در 28 روز گذشته آفلاین بوده است.", + "offline": "نماینده دیگر رای نمی‌دهد و به نظر می‌رسد آفلاین است.", + "overweight": "نماینده بیش از 3M وزن رای نانو دارد. تفویض‌کنندگان باید در نظر بگیرند که وزن را برای بهبود انعطاف‌پذیری و ارزش شبکه توزیع کنند." + }, + "type": { + "behind": "عقب", + "low_uptime": "زمان کم آنلاین", + "offline": "آفلاین", + "overweight": "بیش از حد وزن" + } + }, + "representatives_cemented_by_weight": { + "title": "تفاوت تایید", + "tooltip": "مقدار وزن رای‌دهی که در X تعداد تاییدیه‌ها از گره پیشرو است را نمایش می‌دهد. مفید برای دانستن اینکه چگونه گره‌ها در سراسر شبکه به خوبی هماهنگ و هم‌راستا هستند" + }, + "representatives_checked_by_weight": { + "title": "تفاوت بلوک‌ها", + "tooltip": "مقدار وزن رای‌دهی که در X تعداد بلوک‌ها از گره پیشرو است را نمایش می‌دهد. مفید برای دریافت حسی از اینکه چگونه انتشار بلوک در سراسر شبکه هماهنگ است" + }, + "representative_delegators": { + "showing_top_delegators": "نمایش برترین 100 تفویض‌کننده با حداقل موجودی 1 نانو." + }, + "representative_info": { + "first_seen": "اولین دیدار", + "last_seen": "آخرین دیدار", + "weight_represented": "وزن نمایندگی" + }, + "representative_network": { + "city": "شهر", + "isp": "ISP", + "network": "شبکه", + "provider": "ارائه‌دهنده" + }, + "representative_telemetry": { + "telemetry": "تلمتری", + "telemetry_timestamp": "زمان‌بندی تلمتری" + }, + "representative_uptime": { + "2m_uptime": "زمان آنلاین 2M", + "2w_uptime": "زمان آنلاین 2W", + "3m_uptime": "زمان آنلاین 3M", + "current_status": "وضعیت فعلی", + "down": "خاموش", + "down_for": "خاموش برای", + "operational": "عملیاتی", + "up_for": "روشن برای", + "warning": "هشدار" + }, + "representatives": { + "alias": "نام مستعار", + "cpu_cores": "هسته‌های CPU", + "cpu_model": "مدل CPU", + "tdp": "TDP (wH)", + "protocol_version": "پروتکل", + "last_seen": "آخرین دیدار", + "host_asn": "میزبان ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "مقدار وزن رای‌دهی بر اساس محدودیت پهنای باند تعیین شده محلی توسط هر گره را نمایش می‌دهد" + }, + "representatives_country_by_weight": { + "title": "کشور" + }, + "representatives_offline": { + "account": "حساب آفلاین", + "last_online": "آخرین آنلاین" + }, + "representatives_page": { + "seo_description": "کاوش و تجزیه و تحلیل نمایندگان شبکه نانو", + "seo_title": "کاوشگر نمایندگان نانو", + "telemetry_tab": "تلمتری", + "weight_distribution_tab": "توزیع وزن", + "weight_history_tab": "تاریخچه وزن", + "offline_reps_tab": "نمایندگان آفلاین" + }, + "representatives_provider_by_weight": { + "title": "ارائه‌دهنده میزبانی" + }, + "representatives_quorum_charts": { + "peers_weight": "وزن همتاها", + "quorum_delta": "تفاوت کوروم", + "title": "نمودارهای کوروم", + "trended_weight": "وزن روندی" + }, + "representatives_search": { + "placeholder": "فیلتر بر اساس حساب، نام مستعار، ip" + }, + "representatives_weight": { + "trended": "روندی" + }, + "representatives_weight_chart": { + "title": "توزیع وزن بر اساس نماینده" + }, + "representatives_version_by_weight": { + "title": "نسخه‌ها" + }, + "roadmap": { + "header": { + "subtitle": "اهداف جامعه", + "title": "برنامه‌ریزی" + }, + "seo": { + "description": "نقشه راه توسعه و جامعه نانو", + "tags": [ + "نقشه راه", + "نانو", + "آینده", + "انتشار", + "طراحی", + "وظایف", + "بحث‌ها", + "جامعه", + "سفیران", + "مدیران" + ], + "title": "نقشه راه" + } + }, + "search_bar": { + "placeholder": "جستجو بر اساس آدرس / هش بلوک" + }, + "uptime": { + "now": "اکنون", + "days_ago": "روزها پیش" + } +} diff --git a/locales/fr.json b/locales/fr.json new file mode 100644 index 00000000..a7606e82 --- /dev/null +++ b/locales/fr.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Adresse du Compte", + "change_summary": "Résumé des Changements", + "copy_notification": "Adresse du compte copiée", + "seo_description": "Informations pour le représentant nano", + "seo_title": "Compte Nano", + "telemetry_charts": "Graphiques de Télémétrie", + "unopened_description": "Bien que l'adresse du compte soit valide, aucun bloc n'a été observé. Si du NANO a été envoyé à ce compte, il doit encore publier un bloc correspondant pour recevoir les fonds et établir un solde d'ouverture. Le solde d'un compte ne peut être mis à jour que par le détenteur du compte car il est le seul à pouvoir publier des blocs sur sa chaîne.", + "unopened_note": "Si un bloc d'ouverture a déjà été publié, cela peut prendre quelques instants pour se propager à travers le réseau et être observé par les nœuds de nano.community.", + "unopened_title": "Ce compte n'a pas encore été ouvert" + }, + "account_blocks_summary": { + "first_timestamp": "Premier Horodatage", + "last_timestamp": "Dernier Horodatage", + "max_amount": "Montant Max", + "min_amount": "Montant Min", + "no_records": "Aucun Enregistrement", + "receiving_account": "Compte Récepteur", + "representative_account": "Compte Représentatif", + "sending_account": "Compte Émetteur", + "showing_top_10": "Affichage des 10 meilleurs comptes par total décroissant", + "transactions": "Transactions" + }, + "account_meta": { + "account_info": "Infos du Compte", + "funding_account": "Compte de Financement", + "funding_timestamp": "Horodatage du Financement", + "height": "Hauteur", + "last_modified": "Dernière Modification", + "open_timestamp": "Horodatage d'Ouverture", + "opening_balance": "Solde d'Ouverture", + "receivable_balance": "Solde Recevable" + }, + "block_page": { + "amount": "Montant", + "copy_notification": "Hash du bloc copié", + "delegated_representative": "Représentant Délégué", + "description": "Description", + "epoch_v1": "Époque v1 — Mise à niveau des chaînes de comptes des blocs hérités (ouvrir, recevoir, envoyer, changer) vers des blocs d'état.", + "epoch_v2": "Époque v2 - Mise à niveau des chaînes de comptes pour utiliser une difficulté de Preuve de Travail plus élevée.", + "receiving_account": "Compte Récepteur", + "section_label": "Hash du Bloc", + "sending_account": "Compte Émetteur", + "seo_description": "Informations liées à un Bloc Nano", + "seo_title": "Bloc Nano", + "voting_weight": "Poids de Vote" + }, + "block_info": { + "block_account": "Compte du Bloc", + "operation": "Opération", + "status": "Statut", + "timestamp": "Horodatage" + }, + "block_status": { + "confirmed": "Confirmé", + "unconfirmed": "Non Confirmé" + }, + "block_type": { + "change": "Changement", + "epoch": "Époque", + "open": "Ouvrir", + "receive": "Recevoir", + "send": "Envoyer" + }, + "common": { + "account_one": "Compte", + "account_other": "Comptes", + "address": "Adresse", + "balance": "Solde", + "bandwidth_limit": "Limite de Bande Passante", + "bandwidth_limit_short": "Limite BP", + "blocks": "Blocs", + "blocks_behind": "Blocs en Retard", + "blocks_diff_short": "Diff Blocs", + "by_online_weight": "Par Poids en Ligne", + "clear_filters": "Effacer les Filtres", + "click_to_copy": "Cliquer pour copier", + "collapse": "Réduire", + "conf_short": "Conf.", + "conf_diff_short": "Diff Conf", + "confirmations_behind": "Confirmations en Retard", + "country": "Pays", + "delegator_one": "Délégué", + "delegator_other": "Délégués", + "max": "Max", + "min": "Min", + "offline": "Hors ligne", + "online": "En ligne", + "peers": "Pairs", + "percent_of_total": "% du Total", + "port": "Port", + "quorum_delta": "Delta du Quorum", + "representative_one": "Représentant", + "representative_other": "Représentants", + "show_more": "Afficher {{count}} de plus", + "total": "Total", + "unchecked": "Non vérifié", + "unchecked_count": "Compte Non Vérifié", + "unlimited": "Illimité", + "uptime": "Temps de Fonctionnement", + "version": "Version", + "weight": "Poids" + }, + "delegators": { + "showing_top_delegators": "Affichage des 100 principaux délégateurs avec un solde minimum de 1 Nano." + }, + "doc": { + "contributors": "Contributeur", + "document_not_found": "Document (ou Compte) non trouvé", + "edit_page": "Modifier la Page", + "help_out": "Aider", + "not_found_404": "404", + "section_link_copied": "Lien de section copié", + "updated_by": "mis à jour par" + }, + "github_events": { + "action": { + "added_member": "membre ajouté", + "commented_on_commit": "a commenté le commit", + "commented_on_issue": "a commenté le problème", + "commented_on_pr_review": "a commenté la révision de pr", + "created": "créé {{action}}", + "deleted": "supprimé {{action}}", + "forked": "forké", + "issue_action": "{{action}} problème", + "made_public": "rendu public", + "pr_action": "{{action}} pr", + "pr_review": "révision de pr {{title}}", + "published_release": "publication publiée", + "pushed_commit": "commit poussé à {{ref}}", + "sponsorship_started": "parrainage commencé", + "watching_repo": "suivi du dépôt" + }, + "events_title": "Événements de Développement" + }, + "ledger": { + "addresses": { + "active_detail": "Actif montre le nombre d'adresses uniques utilisées. Nouveau montre le nombre d'adresses créées. Réutilisé montre le nombre d'adresses utilisées qui ont été créées un jour précédent.", + "active_stats": "Statistiques d'Adresses Actives", + "new_stats": "Statistiques de Nouvelles Adresses", + "total_number": "Le nombre total d'adresses actives, nouvelles et réutilisées utilisées par jour." + }, + "amounts": { + "total_number": "Le nombre de blocs de type envoi confirmés par jour où le montant dans le bloc est dans une plage donnée (en Nano)" + }, + "blocks": { + "change": "Statistiques de Blocs de Changement", + "description": "Le nombre de blocs confirmés par jour.", + "open": "Statistiques de Blocs d'Ouverture", + "receive": "Statistiques de Blocs de Réception", + "send": "Statistiques de Blocs d'Envoi", + "total": "Statistiques Totales de Blocs" + }, + "description": "Description", + "usd_transferred": { + "desc_1": "Le montant total de la valeur transférée (en USD) par jour.", + "desc_2": "Basé sur le prix de clôture quotidien de Nano/USD et le montant total de Nano transféré ce jour-là.", + "usd_transferred": "USD Transférés", + "usd_transferred_stats": "Statistiques des USD Transférés" + }, + "volume": { + "change_stats": "Statistiques de Changement", + "description": "Le montant total envoyé (en Nano) et le montant total du poids de vote changé par jour.", + "send_stats": "Statistiques d'Envoi" + } + }, + "ledger_page": { + "addresses_tab": "Adresses", + "amounts_tab": "Montants", + "blocks_tab": "Blocs", + "seo_description": "Métriques et analyses en chaîne du grand livre Nano", + "seo_title": "Analyse du Grand Livre Nano", + "value_transferred_tab": "Valeur Transférée", + "volume_tab": "Volume" + }, + "menu": { + "account_setup": "Configuration du Compte", + "acquiring": "Acquisition", + "advantages": "Avantages", + "attack_vectors": "Vecteurs d'Attaque", + "basics": "Bases", + "best_practices": "Meilleures Pratiques", + "choosing_a_rep": "Choisir un Représentant", + "challenges": "Défis", + "communities": "Communautés", + "contribution_guide": "Guide de Contribution", + "design": "Conception", + "developer_discussions": "Discussions des Développeurs", + "developers": "Développeurs", + "documentation": "Documentation", + "faqs": "FAQs", + "get_involved": "S'impliquer", + "get_support": "Obtenir du Support", + "getting_started": "Commencer", + "glossary": "Glossaire", + "guides": "Guides", + "history": "Histoire", + "home": "Accueil", + "how_it_works": "Comment ça Marche", + "integrations": "Intégrations", + "introduction": "Introduction", + "investment_thesis": "Thèse d'Investissement", + "learn": "Apprendre", + "ledger": "Grand Livre", + "misconceptions": "Idées Fausses", + "overview": "Aperçu", + "planning": "Planification", + "privacy": "Confidentialité", + "protocol": "Protocole", + "running_a_node": "Exécuter un Nœud", + "security": "Sécurité", + "stats": "Statistiques", + "storing": "Stockage", + "telemetry": "Télémétrie", + "topics": "Sujets", + "using": "Utilisation", + "why_it_matters": "Pourquoi C'est Important" + }, + "network": { + "backlog_text": "Nombre médian de transactions en attente de confirmation $(network.pr_text)", + "censor_text": "Le nombre minimum de représentants nécessaires pour censurer les transactions ou paralyser le réseau", + "confirm_text": "Le nombre minimum de représentants nécessaires pour confirmer les transactions", + "confirmations": "Confirmations (24h)", + "confirmations_text": "Nombre total de transactions confirmées par le réseau au cours des dernières 24 heures", + "energy_text": "Estimation de la consommation d'énergie CPU du réseau en direct des représentants principaux basée sur les informations collectées sur le modèle de CPU. L'estimation est basée sur le TDP du CPU, qui est la puissance moyenne, en watts, que le processeur dissipe lorsqu'il fonctionne à la fréquence de base avec tous les cœurs actifs sous une charge de travail complexe définie par le fabricant", + "energy_usage": "Utilisation d'énergie (TDP) (24h)", + "fee_text": "Le réseau Nano fonctionne sans frais", + "nano_ticker": "NanoTicker", + "online_stake": "Enjeu en ligne", + "principal_reps": "Représentants principaux", + "pr_text": "tel qu'observé à travers les représentants principaux du réseau : nœuds de vote avec plus de 0,1 % du poids de vote en ligne qui leur est délégué", + "reps_to_censor": "Représentants pour censurer ou paralyser", + "reps_to_confirm": "Représentants pour confirmer", + "settlement": "Règlement (24h)", + "settlement_text": "Montant total de la valeur réglée par le réseau au cours des dernières 24 heures", + "speed_text": "Temps en millisecondes pour qu'une transaction de test soit confirmée", + "stake_text": "Pourcentage du poids Nano délégué participant activement au vote", + "stats_title": "Statistiques du réseau", + "total_reps": "Total des représentants (24h)", + "tx_backlog": "Arriéré de Tx", + "tx_fees": "Frais de Tx (24h)", + "tx_speed": "Vitesse de Tx", + "tx_throughput": "Débit de Tx", + "throughput_text": "Nombre médian de transactions confirmées par seconde au cours de la dernière minute $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Fondation Nano", + "top": "Top", + "trending": "Tendance" + }, + "representative_alerts": { + "table_header": { + "behind": "Retard", + "issue": "Problème", + "last_online": "Dernière fois en ligne", + "percent_online_weight": "% Poids en ligne", + "representative": "Représentant" + }, + "tooltip": { + "behind": "Le représentant est en retard ou en phase de démarrage. Le seuil est un compte cimenté au-delà du 95e percentile. (via télémétrie)", + "low_uptime": "Le représentant a été hors ligne plus de 25 % au cours des 28 derniers jours.", + "offline": "Le représentant a cessé de voter et semble être hors ligne.", + "overweight": "Le représentant a plus de 3M de poids de vote Nano. Les délégateurs devraient envisager de distribuer le poids pour améliorer la résilience du réseau et sa valeur." + }, + "type": { + "behind": "Retard", + "low_uptime": "Faible disponibilité", + "offline": "Hors ligne", + "overweight": "Surpoids" + } + }, + "representatives_cemented_by_weight": { + "title": "Différentiel de confirmation", + "tooltip": "Affiche la quantité de poids de vote qui est à X nombre de confirmations du nœud leader. Utile pour savoir à quel point les nœuds sont bien synchronisés et alignés à travers le réseau" + }, + "representatives_checked_by_weight": { + "title": "Différentiel de blocs", + "tooltip": "Affiche la quantité de poids de vote qui est à X nombre de blocs du nœud leader. Utile pour avoir une idée de la synchronisation de la propagation des blocs au sein du réseau" + }, + "representative_delegators": { + "showing_top_delegators": "Affichage des 100 principaux délégateurs avec un solde minimum de 1 Nano." + }, + "representative_info": { + "first_seen": "Première apparition", + "last_seen": "Dernière apparition", + "weight_represented": "Poids représenté" + }, + "representative_network": { + "city": "Ville", + "isp": "FAI", + "network": "Réseau", + "provider": "Fournisseur" + }, + "representative_telemetry": { + "telemetry": "Télémétrie", + "telemetry_timestamp": "Horodatage de la télémétrie" + }, + "representative_uptime": { + "2m_uptime": "Disponibilité 2M", + "2w_uptime": "Disponibilité 2S", + "3m_uptime": "Disponibilité 3M", + "current_status": "Statut actuel", + "down": "Hors ligne", + "down_for": "Hors ligne depuis", + "operational": "Opérationnel", + "up_for": "En ligne depuis", + "warning": "Avertissement" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "Cœurs CPU", + "cpu_model": "Modèle CPU", + "tdp": "TDP (wH)", + "protocol_version": "Protocole", + "last_seen": "Dernière vue", + "host_asn": "ASN hôte" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Affiche la quantité de poids de vote basée sur la limite de bande passante définie localement par chaque nœud" + }, + "representatives_country_by_weight": { + "title": "Pays" + }, + "representatives_offline": { + "account": "Compte hors ligne", + "last_online": "Dernière fois en ligne" + }, + "representatives_page": { + "seo_description": "Explorer et analyser les représentants du réseau Nano", + "seo_title": "Explorateur de représentants Nano", + "telemetry_tab": "Télémétrie", + "weight_distribution_tab": "Distribution du poids", + "weight_history_tab": "Historique du poids", + "offline_reps_tab": "Représentants hors ligne" + }, + "representatives_provider_by_weight": { + "title": "Fournisseur d'hébergement" + }, + "representatives_quorum_charts": { + "peers_weight": "Poids des pairs", + "quorum_delta": "Delta du quorum", + "title": "Graphiques du quorum", + "trended_weight": "Poids tendanciel" + }, + "representatives_search": { + "placeholder": "Filtrer par compte, alias, ip" + }, + "representatives_weight": { + "trended": "Tendanciel" + }, + "representatives_weight_chart": { + "title": "Distribution du poids par représentant" + }, + "representatives_version_by_weight": { + "title": "Versions" + }, + "roadmap": { + "header": { + "subtitle": "Objectifs de la communauté", + "title": "Planification" + }, + "seo": { + "description": "Feuille de route du développement et de la communauté Nano", + "tags": [ + "feuille de route", + "nano", + "futur", + "sortie", + "conception", + "tâches", + "discussions", + "communauté", + "ambassadeurs", + "gestionnaires" + ], + "title": "Feuille de route" + } + }, + "search_bar": { + "placeholder": "Rechercher par adresse / hachage de bloc" + }, + "uptime": { + "now": "Maintenant", + "days_ago": "jours passés" + } +} diff --git a/locales/hi.json b/locales/hi.json new file mode 100644 index 00000000..216aa6af --- /dev/null +++ b/locales/hi.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "खाता पता", + "change_summary": "सारांश में परिवर्तन", + "copy_notification": "खाता पता कॉपी किया गया", + "seo_description": "नैनो प्रतिनिधि के लिए जानकारी", + "seo_title": "नैनो खाता", + "telemetry_charts": "टेलीमेट्री चार्ट्स", + "unopened_description": "जबकि खाता पता मान्य है, कोई ब्लॉक नहीं देखा गया है। यदि इस खाते में NANO भेजा गया है, तो धन प्राप्त करने और एक आरंभिक शेष राशि स्थापित करने के लिए अभी भी एक संबंधित ब्लॉक प्रकाशित करने की आवश्यकता है। एक खाते की शेष राशि केवल खाता धारक द्वारा अपडेट की जा सकती है क्योंकि वे ही अपनी श्रृंखला में ब्लॉक प्रकाशित कर सकते हैं।", + "unopened_note": "यदि एक आरंभिक ब्लॉक पहले ही प्रकाशित किया जा चुका है, तो इसे नेटवर्क के माध्यम से फैलने और नैनो.कम्युनिटी नोड्स द्वारा देखे जाने में कुछ समय लग सकता है।", + "unopened_title": "यह खाता अभी तक नहीं खोला गया है" + }, + "account_blocks_summary": { + "first_timestamp": "पहला समयांक", + "last_timestamp": "अंतिम समयांक", + "max_amount": "अधिकतम राशि", + "min_amount": "न्यूनतम राशि", + "no_records": "कोई रिकॉर्ड नहीं", + "receiving_account": "प्राप्त करने वाला खाता", + "representative_account": "प्रतिनिधि खाता", + "sending_account": "भेजने वाला खाता", + "showing_top_10": "कुल अवरोही क्रम में शीर्ष 10 खातों को दिखा रहा है", + "transactions": "लेन-देन" + }, + "account_meta": { + "account_info": "खाता जानकारी", + "funding_account": "फंडिंग खाता", + "funding_timestamp": "फंडिंग समयांक", + "height": "ऊंचाई", + "last_modified": "अंतिम संशोधित", + "open_timestamp": "खुला समयांक", + "opening_balance": "आरंभिक शेष राशि", + "receivable_balance": "प्राप्य शेष राशि" + }, + "block_page": { + "amount": "राशि", + "copy_notification": "ब्लॉक हैश कॉपी किया गया", + "delegated_representative": "प्रतिनिधित्व किया गया प्रतिनिधि", + "description": "विवरण", + "epoch_v1": "युग v1 - पुराने ब्लॉक्स (खुला, प्राप्त, भेजा, परिवर्तन) से राज्य ब्लॉक्स तक खाता-श्रृंखलाओं को उन्नत किया।", + "epoch_v2": "युग v2 - उच्च प्रूफ-ऑफ-वर्क कठिनाई का उपयोग करने के लिए खाता-श्रृंखलाओं को उन्नत किया।", + "receiving_account": "प्राप्त करने वाला खाता", + "section_label": "ब्लॉक हैश", + "sending_account": "भेजने वाला खाता", + "seo_description": "नैनो ब्लॉक से संबंधित जानकारी", + "seo_title": "नैनो ब्लॉक", + "voting_weight": "मतदान वजन" + }, + "block_info": { + "block_account": "ब्लॉक खाता", + "operation": "संचालन", + "status": "स्थिति", + "timestamp": "समयांक" + }, + "block_status": { + "confirmed": "पुष्टि की गई", + "unconfirmed": "अपुष्ट" + }, + "block_type": { + "change": "परिवर्तन", + "epoch": "युग", + "open": "खुला", + "receive": "प्राप्त", + "send": "भेजें" + }, + "common": { + "account_one": "खाता", + "account_other": "खाते", + "address": "पता", + "balance": "शेष राशि", + "bandwidth_limit": "बैंडविड्थ सीमा", + "bandwidth_limit_short": "बीडब्ल्यू सीमा", + "blocks": "ब्लॉक्स", + "blocks_behind": "ब्लॉक्स पीछे", + "blocks_diff_short": "ब्लॉक्स अंतर", + "by_online_weight": "ऑनलाइन वजन द्वारा", + "clear_filters": "फिल्टर साफ करें", + "click_to_copy": "कॉपी करने के लिए क्लिक करें", + "collapse": "संकुचित", + "conf_short": "पुष्टि।", + "conf_diff_short": "पुष्टि अंतर", + "confirmations_behind": "पुष्टियाँ पीछे", + "country": "देश", + "delegator_one": "प्रतिनिधि", + "delegator_other": "प्रतिनिधियों", + "max": "अधिकतम", + "min": "न्यूनतम", + "offline": "ऑफलाइन", + "online": "ऑनलाइन", + "peers": "साथी", + "percent_of_total": "% कुल का", + "port": "पोर्ट", + "quorum_delta": "कोरम डेल्टा", + "representative_one": "प्रतिनिधि", + "representative_other": "प्रतिनिधियों", + "show_more": "{{count}} और दिखाएँ", + "total": "कुल", + "unchecked": "अचेक्ड", + "unchecked_count": "अचेक्ड गणना", + "unlimited": "असीमित", + "uptime": "अपटाइम", + "version": "संस्करण", + "weight": "वजन" + }, + "delegators": { + "showing_top_delegators": "न्यूनतम शेष राशि 1 नैनो के साथ शीर्ष 100 प्रतिनिधियों को दिखा रहा है।" + }, + "doc": { + "contributors": "योगदानकर्ता", + "document_not_found": "दस्तावेज़ (या खाता) नहीं मिला", + "edit_page": "पृष्ठ संपादित करें", + "help_out": "मदद करें", + "not_found_404": "404", + "section_link_copied": "अनुभाग लिंक कॉपी किया गया", + "updated_by": "द्वारा अपडेट किया गया" + }, + "github_events": { + "action": { + "added_member": "सदस्य जोड़ा गया", + "commented_on_commit": "कमिट पर टिप्पणी की", + "commented_on_issue": "मुद्दे पर टिप्पणी की", + "commented_on_pr_review": "पीआर समीक्षा पर टिप्पणी की", + "created": "बनाया गया {{action}}", + "deleted": "हटाया गया {{action}}", + "forked": "फोर्क किया गया", + "issue_action": "{{action}} मुद्दा", + "made_public": "सार्वजनिक किया गया", + "pr_action": "{{action}} पीआर", + "pr_review": "पीआर समीक्षा {{title}}", + "published_release": "प्रकाशित रिलीज़", + "pushed_commit": "{{ref}} में कमिट पुश किया गया", + "sponsorship_started": "प्रायोजन शुरू किया गया", + "watching_repo": "रेपो देख रहे हैं" + }, + "events_title": "विकास घटनाएँ" + }, + "ledger": { + "addresses": { + "active_detail": "सक्रिय वह संख्या दिखाता है जिसमें अद्वितीय पते प्रयुक्त होते हैं। नया उन पतों की संख्या दिखाता है जो बनाए गए हैं। पुन: प्रयुक्त उन पतों की संख्या दिखाता है जो पिछले दिन बनाए गए थे और प्रयुक्त हुए हैं।", + "active_stats": "सक्रिय पते के आँकड़े", + "new_stats": "नए पते के आँकड़े", + "total_number": "प्रति दिन प्रयुक्त सक्रिय, नए, और पुन: प्रयुक्त पतों की कुल संख्या।" + }, + "amounts": { + "total_number": "प्रति दिन पुष्टि किए गए भेजने-प्रकार के ब्लॉकों की संख्या जहाँ ब्लॉक में राशि एक निर्दिष्ट सीमा में होती है (नैनो में)" + }, + "blocks": { + "change": "परिवर्तन ब्लॉक आँकड़े", + "description": "प्रति दिन पुष्टि किए गए ब्लॉकों की संख्या।", + "open": "ओपन ब्लॉक आँकड़े", + "receive": "प्राप्त ब्लॉक आँकड़े", + "send": "भेजें ब्लॉक आँकड़े", + "total": "कुल ब्लॉक आँकड़े" + }, + "description": "विवरण", + "usd_transferred": { + "desc_1": "प्रति दिन स्थानांतरित मूल्य की कुल राशि (USD में)।", + "desc_2": "नैनो/USD की दैनिक समापन मूल्य और उस दिन स्थानांतरित कुल नैनो राशि के आधार पर।", + "usd_transferred": "USD स्थानांतरित", + "usd_transferred_stats": "USD स्थानांतरित आँकड़े" + }, + "volume": { + "change_stats": "परिवर्तन आँकड़े", + "description": "प्रति दिन भेजी गई कुल राशि (नैनो में) और कुल मतदान वजन परिवर्तित।", + "send_stats": "भेजें आँकड़े" + } + }, + "ledger_page": { + "addresses_tab": "पते", + "amounts_tab": "राशियाँ", + "blocks_tab": "ब्लॉक", + "seo_description": "नैनो लेजर के ऑन-चेन मेट्रिक्स और विश्लेषण", + "seo_title": "नैनो लेजर विश्लेषण", + "value_transferred_tab": "मूल्य स्थानांतरित", + "volume_tab": "वॉल्यूम" + }, + "menu": { + "account_setup": "खाता सेटअप", + "acquiring": "प्राप्त करना", + "advantages": "लाभ", + "attack_vectors": "आक्रमण वेक्टर", + "basics": "मूल बातें", + "best_practices": "सर्वोत्तम प्रथाएँ", + "choosing_a_rep": "प्रतिनिधि चुनना", + "challenges": "चुनौतियाँ", + "communities": "समुदाय", + "contribution_guide": "योगदान गाइड", + "design": "डिज़ाइन", + "developer_discussions": "डेवलपर चर्चाएँ", + "developers": "डेवलपर्स", + "documentation": "दस्तावेज़ीकरण", + "faqs": "पूछे जाने वाले प्रश्न", + "get_involved": "शामिल हों", + "get_support": "समर्थन प्राप्त करें", + "getting_started": "शुरू करना", + "glossary": "शब्दावली", + "guides": "गाइड", + "history": "इतिहास", + "home": "होम", + "how_it_works": "यह कैसे काम करता है", + "integrations": "एकीकरण", + "introduction": "परिचय", + "investment_thesis": "निवेश थीसिस", + "learn": "सीखें", + "ledger": "लेजर", + "misconceptions": "गलतफहमियाँ", + "overview": "अवलोकन", + "planning": "योजना बनाना 👾", + "privacy": "गोपनीयता", + "protocol": "प्रोटोकॉल", + "running_a_node": "नोड चलाना", + "security": "सुरक्षा", + "stats": "आँकड़े", + "storing": "संग्रहण", + "telemetry": "टेलीमेट्री", + "topics": "विषय", + "using": "उपयोग करना", + "why_it_matters": "यह क्यों महत्वपूर्ण है" + }, + "network": { + "backlog_text": "पुष्टि की प्रतीक्षा कर रहे लेन-देनों की मध्य संख्या $(network.pr_text)", + "censor_text": "लेन-देनों को सेंसर करने या नेटवर्क को रोकने के लिए आवश्यक न्यूनतम प्रतिनिधियों की संख्या", + "confirm_text": "लेन-देनों की पुष्टि करने के लिए आवश्यक न्यूनतम प्रतिनिधियों की संख्या", + "confirmations": "पुष्टिकरण (24घंटे)", + "confirmations_text": "पिछले 24 घंटों में नेटवर्क द्वारा पुष्टि किए गए लेन-देनों की कुल संख्या", + "energy_text": "संग्रहीत CPU मॉडल जानकारी के आधार पर प्रिंसिपल प्रतिनिधियों के लाइव नेटवर्क CPU ऊर्जा उपयोग का अनुमान। अनुमान CPU TDP पर आधारित है, जो वाट्स में औसत शक्ति है, जो प्रोसेसर निर्माता-परिभाषित, उच्च-जटिलता के कार्यभार के तहत सभी कोर सक्रिय होने पर बेस फ्रीक्वेंसी पर संचालित होते समय विसर्जित करता है", + "energy_usage": "ऊर्जा उपयोग (TDP) (24घंटे)", + "fee_text": "नैनो नेटवर्क बिना शुल्क के संचालित होता है", + "nano_ticker": "नैनो टिकर", + "online_stake": "ऑनलाइन हिस्सेदारी", + "principal_reps": "प्रिंसिपल प्रतिनिधि", + "pr_text": "नेटवर्क के प्रिंसिपल प्रतिनिधियों में देखा गया: वोटिंग नोड्स जिन्हें ऑनलाइन वोटिंग वजन का 0.1% से अधिक डेलिगेट किया गया है", + "reps_to_censor": "सेंसर या रोकने के लिए प्रतिनिधि", + "reps_to_confirm": "पुष्टि करने के लिए प्रतिनिधि", + "settlement": "निपटान (24घंटे)", + "settlement_text": "पिछले 24 घंटों में नेटवर्क द्वारा निपटान की गई मूल्य की कुल राशि", + "speed_text": "एक परीक्षण लेन-देन की पुष्टि करने के लिए मिलीसेकंड में समय", + "stake_text": "वोटिंग में सक्रिय रूप से भाग लेने वाले डेलिगेटेड नैनो वजन का प्रतिशत", + "stats_title": "नेटवर्क आँकड़े", + "total_reps": "कुल प्रतिनिधि (24घंटे)", + "tx_backlog": "टीएक्स बैकलॉग", + "tx_fees": "टीएक्स शुल्क (24घंटे)", + "tx_speed": "टीएक्स गति", + "tx_throughput": "टीएक्स थ्रूपुट", + "throughput_text": "पिछले मिनट में प्रति सेकंड पुष्टि किए गए लेन-देनों की मध्य संख्या $(network.pr_text)" + }, + "posts": { + "nano_foundation": "नैनो फाउंडेशन", + "top": "शीर्ष", + "trending": "ट्रेंडिंग" + }, + "representative_alerts": { + "table_header": { + "behind": "पीछे", + "issue": "मुद्दा", + "last_online": "अंतिम ऑनलाइन", + "percent_online_weight": "% ऑनलाइन वजन", + "representative": "प्रतिनिधि" + }, + "tooltip": { + "behind": "प्रतिनिधि पीछे है या बूटस्ट्रैपिंग कर रहा है। कटऑफ 95वें पर्सेंटाइल से परे एक सीमेंटेड काउंट है। (टेलीमेट्री के माध्यम से)", + "low_uptime": "प्रतिनिधि पिछले 28 दिनों में 25% से अधिक समय ऑफलाइन रहा है।", + "offline": "प्रतिनिधि ने वोटिंग बंद कर दी है और ऑफलाइन प्रतीत होता है।", + "overweight": "प्रतिनिधि के पास 3M नैनो वोटिंग वजन से अधिक है। डेलिगेटर्स को नेटवर्क की लचीलापन और मूल्य में सुधार के लिए वजन को वितरित करने पर विचार करना चाहिए।" + }, + "type": { + "behind": "पीछे", + "low_uptime": "कम अपटाइम", + "offline": "ऑफलाइन", + "overweight": "अधिक वजन" + } + }, + "representatives_cemented_by_weight": { + "title": "पुष्टिकरण अंतर", + "tooltip": "वोटिंग वजन की राशि दिखाता है जो अग्रणी नोड से X संख्या में पुष्टिकरणों के भीतर है। नोड्स नेटवर्क भर में कितने अच्छी तरह से सिंक और संरेखित हैं, इसकी जानकारी देने में सहायक" + }, + "representatives_checked_by_weight": { + "title": "ब्लॉक्स अंतर", + "tooltip": "वोटिंग वजन की राशि दिखाता है जो अग्रणी नोड से X संख्या में ब्लॉक्स के भीतर है। नेटवर्क के भीतर ब्लॉक प्रसारण कितना सिंक में है, इसकी भावना प्राप्त करने के लिए उपयोगी" + }, + "representative_delegators": { + "showing_top_delegators": "1 नैनो की न्यूनतम शेष राशि के साथ शीर्ष 100 डेलिगेटर्स दिखा रहा है।" + }, + "representative_info": { + "first_seen": "पहली बार देखा गया", + "last_seen": "अंतिम बार देखा गया", + "weight_represented": "प्रतिनिधित्व वजन" + }, + "representative_network": { + "city": "शहर", + "isp": "आईएसपी", + "network": "नेटवर्क", + "provider": "प्रदाता" + }, + "representative_telemetry": { + "telemetry": "टेलीमेट्री", + "telemetry_timestamp": "टेलीमेट्री टाइमस्टैम्प" + }, + "representative_uptime": { + "2m_uptime": "2M अपटाइम", + "2w_uptime": "2W अपटाइम", + "3m_uptime": "3M अपटाइम", + "current_status": "वर्तमान स्थिति", + "down": "नीचे", + "down_for": "के लिए नीचे", + "operational": "संचालनात्मक", + "up_for": "के लिए ऊपर", + "warning": "चेतावनी" + }, + "representatives": { + "alias": "उपनाम", + "cpu_cores": "सीपीयू कोर", + "cpu_model": "सीपीयू मॉडल", + "tdp": "टीडीपी (wH)", + "protocol_version": "प्रोटोकॉल", + "last_seen": "अंतिम बार देखा गया", + "host_asn": "होस्ट एएसएन" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "प्रत्येक नोड द्वारा स्थानीय रूप से सेट बैंडविड्थ सीमा के आधार पर वोटिंग वजन की राशि प्रदर्शित करता है" + }, + "representatives_country_by_weight": { + "title": "देश" + }, + "representatives_offline": { + "account": "ऑफलाइन खाता", + "last_online": "अंतिम ऑनलाइन" + }, + "representatives_page": { + "seo_description": "नैनो नेटवर्क प्रतिनिधियों का पता लगाएं और विश्लेषण करें", + "seo_title": "नैनो प्रतिनिधि एक्सप्लोरर", + "telemetry_tab": "टेलीमेट्री", + "weight_distribution_tab": "वजन वितरण", + "weight_history_tab": "वजन इतिहास", + "offline_reps_tab": "ऑफलाइन प्रतिनिधि" + }, + "representatives_provider_by_weight": { + "title": "होस्टिंग प्रदाता" + }, + "representatives_quorum_charts": { + "peers_weight": "साथियों का वजन", + "quorum_delta": "कोरम डेल्टा", + "title": "कोरम चार्ट्स", + "trended_weight": "प्रवृत्त वजन" + }, + "representatives_search": { + "placeholder": "खाता, उपनाम, आईपी द्वारा फ़िल्टर करें" + }, + "representatives_weight": { + "trended": "प्रवृत्त" + }, + "representatives_weight_chart": { + "title": "प्रतिनिधि द्वारा वजन वितरण" + }, + "representatives_version_by_weight": { + "title": "संस्करण" + }, + "roadmap": { + "header": { + "subtitle": "समुदाय उद्देश्य", + "title": "योजना" + }, + "seo": { + "description": "नैनो विकास और समुदाय रोडमैप", + "tags": [ + "रोडमैप", + "नैनो", + "भविष्य", + "रिलीज", + "डिज़ाइन", + "कार्य", + "चर्चाएँ", + "समुदाय", + "दूत", + "प्रबंधक" + ], + "title": "रोडमैप" + } + }, + "search_bar": { + "placeholder": "पता / ब्लॉक हैश द्वारा खोजें" + }, + "uptime": { + "now": "अभी", + "days_ago": "दिन पहले" + } +} diff --git a/locales/it.json b/locales/it.json new file mode 100644 index 00000000..5137017b --- /dev/null +++ b/locales/it.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Indirizzo Account", + "change_summary": "Riepilogo Modifiche", + "copy_notification": "Indirizzo account copiato", + "seo_description": "Informazioni per rappresentante nano", + "seo_title": "Account Nano", + "telemetry_charts": "Grafici Telemetria", + "unopened_description": "Sebbene l'indirizzo dell'account sia valido, non sono stati osservati blocchi. Se NANO è stato inviato a questo account, è ancora necessario pubblicare un blocco corrispondente per ricevere i fondi e stabilire un saldo di apertura. Il saldo di un account può essere aggiornato solo dal titolare dell'account poiché sono gli unici che possono pubblicare blocchi sulla loro catena.", + "unopened_note": "Se un blocco di apertura è già stato pubblicato, potrebbe richiedere alcuni momenti per diffondersi attraverso la rete ed essere osservato dai nodi di nano.community.", + "unopened_title": "Questo account non è stato ancora aperto" + }, + "account_blocks_summary": { + "first_timestamp": "Primo Timestamp", + "last_timestamp": "Ultimo Timestamp", + "max_amount": "Importo Massimo", + "min_amount": "Importo Minimo", + "no_records": "Nessun Record", + "receiving_account": "Account Ricevente", + "representative_account": "Account Rappresentante", + "sending_account": "Account Mittente", + "showing_top_10": "Mostrando i primi 10 account per totale discendente", + "transactions": "Transazioni" + }, + "account_meta": { + "account_info": "Informazioni Account", + "funding_account": "Account di Finanziamento", + "funding_timestamp": "Timestamp di Finanziamento", + "height": "Altezza", + "last_modified": "Ultima Modifica", + "open_timestamp": "Timestamp di Apertura", + "opening_balance": "Saldo di Apertura", + "receivable_balance": "Saldo Ricevibile" + }, + "block_page": { + "amount": "Importo", + "copy_notification": "Hash del blocco copiato", + "delegated_representative": "Rappresentante Delegato", + "description": "Descrizione", + "epoch_v1": "Epoca v1 — Aggiornamento delle catene di account dai blocchi legacy (apertura, ricezione, invio, cambio) ai blocchi di stato.", + "epoch_v2": "Epoca v2 - Aggiornamento delle catene di account per utilizzare una difficoltà di Proof-of-Work più elevata.", + "receiving_account": "Account Ricevente", + "section_label": "Hash del Blocco", + "sending_account": "Account Mittente", + "seo_description": "Informazioni relative a un Blocco Nano", + "seo_title": "Blocco Nano", + "voting_weight": "Peso di Voto" + }, + "block_info": { + "block_account": "Account del Blocco", + "operation": "Operazione", + "status": "Stato", + "timestamp": "Timestamp" + }, + "block_status": { + "confirmed": "Confermato", + "unconfirmed": "Non confermato" + }, + "block_type": { + "change": "Cambio", + "epoch": "Epoca", + "open": "Apertura", + "receive": "Ricezione", + "send": "Invio" + }, + "common": { + "account_one": "Account", + "account_other": "Account", + "address": "Indirizzo", + "balance": "Saldo", + "bandwidth_limit": "Limite di Banda", + "bandwidth_limit_short": "Limite BW", + "blocks": "Blocchi", + "blocks_behind": "Blocchi Indietro", + "blocks_diff_short": "Diff Blocchi", + "by_online_weight": "Per Peso Online", + "clear_filters": "Cancella Filtri", + "click_to_copy": "Clicca per copiare", + "collapse": "Collassa", + "conf_short": "Conf.", + "conf_diff_short": "Diff Conf.", + "confirmations_behind": "Conferme Indietro", + "country": "Paese", + "delegator_one": "Delegante", + "delegator_other": "Deleganti", + "max": "Max", + "min": "Min", + "offline": "Offline", + "online": "Online", + "peers": "Peer", + "percent_of_total": "% del Totale", + "port": "Porta", + "quorum_delta": "Delta del Quorum", + "representative_one": "Rappresentante", + "representative_other": "Rappresentanti", + "show_more": "Mostra altri {{count}}", + "total": "Totale", + "unchecked": "Non verificato", + "unchecked_count": "Conteggio Non Verificato", + "unlimited": "Illimitato", + "uptime": "Tempo di Attività", + "version": "Versione", + "weight": "Peso" + }, + "delegators": { + "showing_top_delegators": "Mostrando i primi 100 deleganti con un saldo minimo di 1 Nano." + }, + "doc": { + "contributors": "Contributore", + "document_not_found": "Documento (o Account) non trovato", + "edit_page": "Modifica Pagina", + "help_out": "Aiuta", + "not_found_404": "404", + "section_link_copied": "Link sezione copiato", + "updated_by": "aggiornato da" + }, + "github_events": { + "action": { + "added_member": "membro aggiunto", + "commented_on_commit": "commentato su commit", + "commented_on_issue": "commentato su problema", + "commented_on_pr_review": "commentato su revisione pr", + "created": "creato {{action}}", + "deleted": "eliminato {{action}}", + "forked": "forkato", + "issue_action": "{{action}} problema", + "made_public": "reso pubblico", + "pr_action": "{{action}} pr", + "pr_review": "revisione pr {{title}}", + "published_release": "rilascio pubblicato", + "pushed_commit": "commit spinto su {{ref}}", + "sponsorship_started": "sponsorizzazione iniziata", + "watching_repo": "osservando repo" + }, + "events_title": "Eventi di Sviluppo" + }, + "ledger": { + "addresses": { + "active_detail": "Attivo mostra il numero di indirizzi unici utilizzati. Nuovo mostra il numero di indirizzi creati. Riutilizzato mostra il numero di indirizzi utilizzati che sono stati creati in un giorno precedente.", + "active_stats": "Statistiche Indirizzi Attivi", + "new_stats": "Statistiche Nuovi Indirizzi", + "total_number": "Il numero totale di indirizzi attivi, nuovi e riutilizzati utilizzati al giorno." + }, + "amounts": { + "total_number": "Il numero di blocchi di tipo invio confermati al giorno dove l'importo nel blocco è in un dato intervallo (in Nano)" + }, + "blocks": { + "change": "Statistiche Blocchi di Cambiamento", + "description": "Il numero di blocchi confermati al giorno.", + "open": "Statistiche Blocchi di Apertura", + "receive": "Statistiche Blocchi di Ricezione", + "send": "Statistiche Blocchi di Invio", + "total": "Statistiche Totali dei Blocchi" + }, + "description": "Descrizione", + "usd_transferred": { + "desc_1": "L'importo totale del valore trasferito (in USD) al giorno.", + "desc_2": "Basato sul prezzo di chiusura giornaliero di Nano/USD e l'importo totale di Nano trasferito quel giorno.", + "usd_transferred": "USD Trasferiti", + "usd_transferred_stats": "Statistiche USD Trasferiti" + }, + "volume": { + "change_stats": "Statistiche di Cambiamento", + "description": "L'importo totale inviato (in Nano) e l'importo totale del peso di voto cambiato al giorno.", + "send_stats": "Statistiche di Invio" + } + }, + "ledger_page": { + "addresses_tab": "Indirizzi", + "amounts_tab": "Importi", + "blocks_tab": "Blocchi", + "seo_description": "Metriche e analisi on-chain del registro Nano", + "seo_title": "Analisi del Registro Nano", + "value_transferred_tab": "Valore Trasferito", + "volume_tab": "Volume" + }, + "menu": { + "account_setup": "Configurazione Account", + "acquiring": "Acquisizione", + "advantages": "Vantaggi", + "attack_vectors": "Vettori di Attacco", + "basics": "Basi", + "best_practices": "Migliori Pratiche", + "choosing_a_rep": "Scegliere un Rappresentante", + "challenges": "Sfide", + "communities": "Comunità", + "contribution_guide": "Guida al Contributo", + "design": "Design", + "developer_discussions": "Discussioni degli Sviluppatori", + "developers": "Sviluppatori", + "documentation": "Documentazione", + "faqs": "FAQ", + "get_involved": "Partecipa", + "get_support": "Ottieni Supporto", + "getting_started": "Iniziare", + "glossary": "Glossario", + "guides": "Guide", + "history": "Storia", + "home": "Home", + "how_it_works": "Come Funziona", + "integrations": "Integrazioni", + "introduction": "Introduzione", + "investment_thesis": "Tesi di Investimento", + "learn": "Impara", + "ledger": "Registro", + "misconceptions": "Malintesi", + "overview": "Panoramica", + "planning": "Pianificazione", + "privacy": "Privacy", + "protocol": "Protocollo", + "running_a_node": "Gestire un Nodo", + "security": "Sicurezza", + "stats": "Statistiche", + "storing": "Conservazione", + "telemetry": "Telemetria", + "topics": "Argomenti", + "using": "Utilizzo", + "why_it_matters": "Perché È Importante" + }, + "network": { + "backlog_text": "Numero mediano di transazioni in attesa di essere confermate $(network.pr_text)", + "censor_text": "Il numero minimo di rappresentanti necessari per censurare le transazioni o bloccare la rete", + "confirm_text": "Il numero minimo di rappresentanti necessari per confermare le transazioni", + "confirmations": "Conferme (24h)", + "confirmations_text": "Numero totale di transazioni confermate dalla rete nelle ultime 24 ore", + "energy_text": "Stima dell'uso di energia CPU della rete live dei Rappresentanti Principali basata sulle informazioni raccolte sul modello di CPU. La stima si basa sul TDP del CPU, che è la potenza media, in watt, che il processore dissipa quando opera alla frequenza di base con tutti i core attivi sotto un carico di lavoro ad alta complessità definito dal produttore", + "energy_usage": "Uso di Energia (TDP) (24h)", + "fee_text": "La rete Nano opera senza commissioni", + "nano_ticker": "NanoTicker", + "online_stake": "Stake Online", + "principal_reps": "Rappresentanti Principali", + "pr_text": "come osservato attraverso i rappresentanti principali della rete: nodi di voto con più dello 0,1% del peso di voto online a loro delegato", + "reps_to_censor": "Rappresentanti per Censurare o Bloccare", + "reps_to_confirm": "Rappresentanti per Confermare", + "settlement": "Liquidazione (24h)", + "settlement_text": "Importo totale del valore liquidato dalla rete nelle ultime 24 ore", + "speed_text": "Tempo in millisecondi affinché una transazione di prova venga confermata", + "stake_text": "Percentuale del peso Nano delegato che partecipa attivamente al voto", + "stats_title": "Statistiche della Rete", + "total_reps": "Rappresentanti Totali (24h)", + "tx_backlog": "Arretrato Tx", + "tx_fees": "Commissioni Tx (24h)", + "tx_speed": "Velocità Tx", + "tx_throughput": "Throughput Tx", + "throughput_text": "Numero mediano di transazioni confermate al secondo nell'ultimo minuto $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Fondazione Nano", + "top": "Top", + "trending": "Di Tendenza" + }, + "representative_alerts": { + "table_header": { + "behind": "Indietro", + "issue": "Problema", + "last_online": "Ultima Volta Online", + "percent_online_weight": "% Peso Online", + "representative": "Rappresentante" + }, + "tooltip": { + "behind": "Il rappresentante è indietro o sta eseguendo il bootstrap. Il limite è un conteggio cementato oltre il 95° percentile. (tramite telemetria)", + "low_uptime": "Il rappresentante è stato offline più del 25% negli ultimi 28 giorni.", + "offline": "Il rappresentante ha smesso di votare e sembra offline.", + "overweight": "Il rappresentante ha oltre 3M di peso di voto Nano. I deleganti dovrebbero considerare di distribuire il peso per migliorare la resilienza della rete e il suo valore." + }, + "type": { + "behind": "Indietro", + "low_uptime": "Bassa Disponibilità", + "offline": "Offline", + "overweight": "Sovrappeso" + } + }, + "representatives_cemented_by_weight": { + "title": "Differenziale di Conferma", + "tooltip": "Mostra la quantità di peso di voto che si trova entro un numero X di conferme dal nodo leader. Utile per sapere quanto bene i nodi sono sincronizzati e allineati attraverso la rete" + }, + "representatives_checked_by_weight": { + "title": "Differenziale di Blocchi", + "tooltip": "Mostra la quantità di peso di voto che si trova entro un numero X di blocchi dal nodo leader. Utile per avere un'idea di quanto bene la propagazione dei blocchi sia sincronizzata all'interno della rete" + }, + "representative_delegators": { + "showing_top_delegators": "Mostrando i primi 100 deleganti con un saldo minimo di 1 Nano." + }, + "representative_info": { + "first_seen": "Prima Vista", + "last_seen": "Ultima Vista", + "weight_represented": "Peso Rappresentato" + }, + "representative_network": { + "city": "Città", + "isp": "ISP", + "network": "Rete", + "provider": "Fornitore" + }, + "representative_telemetry": { + "telemetry": "Telemetria", + "telemetry_timestamp": "Timestamp Telemetria" + }, + "representative_uptime": { + "2m_uptime": "Disponibilità 2M", + "2w_uptime": "Disponibilità 2S", + "3m_uptime": "Disponibilità 3M", + "current_status": "Stato Attuale", + "down": "Giù", + "down_for": "Giù Per", + "operational": "Operativo", + "up_for": "Su Per", + "warning": "Avvertimento" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "Core CPU", + "cpu_model": "Modello CPU", + "tdp": "TDP (wH)", + "protocol_version": "Protocollo", + "last_seen": "Ultima Vista", + "host_asn": "ASN Host" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Mostra la quantità di peso di voto basata sul limite di banda impostato localmente da ciascun nodo" + }, + "representatives_country_by_weight": { + "title": "Paese" + }, + "representatives_offline": { + "account": "Account Offline", + "last_online": "Ultima Volta Online" + }, + "representatives_page": { + "seo_description": "Esplora e analizza i rappresentanti della rete Nano", + "seo_title": "Esploratore dei Rappresentanti Nano", + "telemetry_tab": "Telemetria", + "weight_distribution_tab": "Distribuzione del Peso", + "weight_history_tab": "Storia del Peso", + "offline_reps_tab": "Rappresentanti Offline" + }, + "representatives_provider_by_weight": { + "title": "Fornitore di Hosting" + }, + "representatives_quorum_charts": { + "peers_weight": "Peso dei Peers", + "quorum_delta": "Delta del Quorum", + "title": "Grafici del Quorum", + "trended_weight": "Peso Tendenziale" + }, + "representatives_search": { + "placeholder": "Filtra per account, alias, ip" + }, + "representatives_weight": { + "trended": "Tendenziale" + }, + "representatives_weight_chart": { + "title": "Distribuzione del Peso per Rappresentante" + }, + "representatives_version_by_weight": { + "title": "Versioni" + }, + "roadmap": { + "header": { + "subtitle": "Obiettivi della comunità", + "title": "Pianificazione" + }, + "seo": { + "description": "Sviluppo di Nano & roadmap della comunità", + "tags": [ + "roadmap", + "nano", + "futuro", + "rilascio", + "design", + "compiti", + "discussioni", + "comunità", + "ambasciatori", + "gestori" + ], + "title": "Roadmap" + } + }, + "search_bar": { + "placeholder": "Cerca per Indirizzo / Hash del Blocco" + }, + "uptime": { + "now": "Adesso", + "days_ago": "giorni fa" + } +} diff --git a/locales/ja.json b/locales/ja.json new file mode 100644 index 00000000..9f917938 --- /dev/null +++ b/locales/ja.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "アカウントアドレス", + "change_summary": "変更概要", + "copy_notification": "アカウントアドレスをコピーしました", + "seo_description": "ナノ代表のための情報", + "seo_title": "ナノアカウント", + "telemetry_charts": "テレメトリチャート", + "unopened_description": "アカウントアドレスは有効ですが、ブロックは観測されていません。NANOがこのアカウントに送信された場合、資金を受け取り、開始残高を確立するために、対応するブロックを公開する必要があります。アカウントの残高は、アカウント保持者のみが自分のチェーンにブロックを公開できるため、アカウント保持者によってのみ更新できます。", + "unopened_note": "開始ブロックが既に公開されている場合、ネットワークを通じて広がり、nano.communityノードによって観測されるまでに数分かかる場合があります。", + "unopened_title": "このアカウントはまだ開設されていません" + }, + "account_blocks_summary": { + "first_timestamp": "最初のタイムスタンプ", + "last_timestamp": "最後のタイムスタンプ", + "max_amount": "最大金額", + "min_amount": "最小金額", + "no_records": "記録なし", + "receiving_account": "受取アカウント", + "representative_account": "代表アカウント", + "sending_account": "送信アカウント", + "showing_top_10": "合計降順でトップ10アカウントを表示", + "transactions": "トランザクション" + }, + "account_meta": { + "account_info": "アカウント情報", + "funding_account": "資金提供アカウント", + "funding_timestamp": "資金提供タイムスタンプ", + "height": "高さ", + "last_modified": "最終更新", + "open_timestamp": "オープンタイムスタンプ", + "opening_balance": "開始残高", + "receivable_balance": "受取可能残高" + }, + "block_page": { + "amount": "金額", + "copy_notification": "ブロックハッシュをコピーしました", + "delegated_representative": "委任された代表", + "description": "説明", + "epoch_v1": "エポックv1 - レガシーブロック(オープン、受信、送信、変更)からステートブロックへのアカウントチェーンのアップグレード。", + "epoch_v2": "エポックv2 - 高いProof-of-Work難易度を使用するためのアカウントチェーンのアップグレード。", + "receiving_account": "受取アカウント", + "section_label": "ブロックハッシュ", + "sending_account": "送信アカウント", + "seo_description": "ナノブロックに関連する情報", + "seo_title": "ナノブロック", + "voting_weight": "投票重み" + }, + "block_info": { + "block_account": "ブロックアカウント", + "operation": "操作", + "status": "ステータス", + "timestamp": "タイムスタンプ" + }, + "block_status": { + "confirmed": "確認済み", + "unconfirmed": "未確認" + }, + "block_type": { + "change": "変更", + "epoch": "エポック", + "open": "オープン", + "receive": "受け取る", + "send": "送る" + }, + "common": { + "account_one": "アカウント", + "account_other": "アカウント", + "address": "アドレス", + "balance": "残高", + "bandwidth_limit": "帯域幅制限", + "bandwidth_limit_short": "BW制限", + "blocks": "ブロック", + "blocks_behind": "ブロック遅延", + "blocks_diff_short": "ブロック差", + "by_online_weight": "オンライン重みによる", + "clear_filters": "フィルターをクリア", + "click_to_copy": "クリックしてコピー", + "collapse": "折りたたむ", + "conf_short": "確認", + "conf_diff_short": "確認差", + "confirmations_behind": "確認遅延", + "country": "国", + "delegator_one": "委任者", + "delegator_other": "委任者", + "max": "最大", + "min": "最小", + "offline": "オフライン", + "online": "オンライン", + "peers": "ピア", + "percent_of_total": "総数の%", + "port": "ポート", + "quorum_delta": "クォーラムデルタ", + "representative_one": "代表", + "representative_other": "代表", + "show_more": "{{count}} さらに表示", + "total": "合計", + "unchecked": "未チェック", + "unchecked_count": "未チェック数", + "unlimited": "無制限", + "uptime": "稼働時間", + "version": "バージョン", + "weight": "重み" + }, + "delegators": { + "showing_top_delegators": "最小残高1ナノを持つトップ100委任者を表示" + }, + "doc": { + "contributors": "貢献者", + "document_not_found": "ドキュメント(またはアカウント)が見つかりません", + "edit_page": "ページを編集", + "help_out": "助ける", + "not_found_404": "404", + "section_link_copied": "セクションリンクをコピーしました", + "updated_by": "更新者" + }, + "github_events": { + "action": { + "added_member": "メンバーを追加しました", + "commented_on_commit": "コミットにコメントしました", + "commented_on_issue": "イシューにコメントしました", + "commented_on_pr_review": "PRレビューにコメントしました", + "created": "{{action}}を作成しました", + "deleted": "{{action}}を削除しました", + "forked": "フォークしました", + "issue_action": "{{action}}イシュー", + "made_public": "公開しました", + "pr_action": "{{action}}PR", + "pr_review": "PRレビュー{{title}}", + "published_release": "リリースを公開しました", + "pushed_commit": "{{ref}}にコミットをプッシュしました", + "sponsorship_started": "スポンサーシップを開始しました", + "watching_repo": "リポジトリをウォッチしています" + }, + "events_title": "開発イベント" + }, + "ledger": { + "addresses": { + "active_detail": "アクティブは使用されたユニークアドレスの数を示します。新規は作成されたアドレスの数を示します。再利用は以前の日に作成されたアドレスが使用された数を示します。", + "active_stats": "アクティブアドレス統計", + "new_stats": "新規アドレス統計", + "total_number": "日ごとに使用されるアクティブ、新規、再利用アドレスの総数。" + }, + "amounts": { + "total_number": "指定された範囲内のブロックの金額で、1日に確認された送信タイプのブロックの数" + }, + "blocks": { + "change": "変更ブロック統計", + "description": "1日あたりの確認されたブロック数。", + "open": "オープンブロック統計", + "receive": "受信ブロック統計", + "send": "送信ブロック統計", + "total": "総ブロック統計" + }, + "description": "説明", + "usd_transferred": { + "desc_1": "1日あたりに転送された総価値(USD)。", + "desc_2": "Nano/USDの日次終値とその日に転送されたNanoの総量に基づく。", + "usd_transferred": "転送されたUSD", + "usd_transferred_stats": "転送されたUSDの統計" + }, + "volume": { + "change_stats": "変更統計", + "description": "1日あたりに送信された総量(Nano)と総投票重量の変更。", + "send_stats": "送信統計" + } + }, + "ledger_page": { + "addresses_tab": "アドレス", + "amounts_tab": "金額", + "blocks_tab": "ブロック", + "seo_description": "Nanoレジャーのオンチェーンメトリクスと分析", + "seo_title": "Nanoレジャー分析", + "value_transferred_tab": "送金額", + "volume_tab": "ボリューム" + }, + "menu": { + "account_setup": "アカウント設定", + "acquiring": "取得", + "advantages": "利点", + "attack_vectors": "攻撃ベクトル", + "basics": "基本", + "best_practices": "ベストプラクティス", + "choosing_a_rep": "代表選び", + "challenges": "課題", + "communities": "コミュニティ", + "contribution_guide": "貢献ガイド", + "design": "デザイン", + "developer_discussions": "開発者ディスカッション", + "developers": "開発者", + "documentation": "ドキュメンテーション", + "faqs": "FAQ", + "get_involved": "参加する", + "get_support": "サポートを受ける", + "getting_started": "はじめに", + "glossary": "用語集", + "guides": "ガイド", + "history": "歴史", + "home": "ホーム", + "how_it_works": "仕組み", + "integrations": "統合", + "introduction": "イントロダクション", + "investment_thesis": "投資テーゼ", + "learn": "学ぶ", + "ledger": "レジャー", + "misconceptions": "誤解", + "overview": "概要", + "planning": "計画", + "privacy": "プライバシー", + "protocol": "プロトコル", + "running_a_node": "ノードの運用", + "security": "セキュリティ", + "stats": "統計", + "storing": "保管", + "telemetry": "テレメトリ", + "topics": "トピック", + "using": "使用方法", + "why_it_matters": "その重要性" + }, + "network": { + "backlog_text": "確認待ちトランザクションの中央値 $(network.pr_text)", + "censor_text": "トランザクションを検閲またはネットワークを停止させるために必要な代表者の最小数", + "confirm_text": "トランザクションを確認するために必要な代表者の最小数", + "confirmations": "確認数 (24h)", + "confirmations_text": "過去24時間にネットワークによって確認されたトランザクションの総数", + "energy_text": "収集されたCPUモデル情報に基づく、プリンシパル代表者のライブネットワークCPUエネルギー使用量の推定値。推定値はCPU TDP(製造定義の高複雑性ワークロードで全コアがアクティブな基本周波数で動作しているときにプロセッサが放散する平均電力(ワット))に基づいています", + "energy_usage": "エネルギー使用量 (TDP) (24h)", + "fee_text": "Nanoネットワークは手数料なしで運用されます", + "nano_ticker": "Nanoティッカー", + "online_stake": "オンラインステーク", + "principal_reps": "プリンシパル代表者", + "pr_text": "オンライン投票重量の0.1%以上が委任されている投票ノード:ネットワークのプリンシパル代表者を通じて観測されます", + "reps_to_censor": "検閲または停止するための代表者", + "reps_to_confirm": "トランザクションを確認するための代表者", + "settlement": "決済 (24h)", + "settlement_text": "過去24時間にネットワークによって決済された総額", + "speed_text": "テストトランザクションが確認されるまでのミリ秒", + "stake_text": "投票に積極的に参加しているNano重量の割合", + "stats_title": "ネットワーク統計", + "total_reps": "総代表者数 (24h)", + "tx_backlog": "トランザクションバックログ", + "tx_fees": "トランザクション手数料 (24h)", + "tx_speed": "トランザクション速度", + "tx_throughput": "トランザクションスループット", + "throughput_text": "過去1分間に秒間に確認されたトランザクションの中央値 $(network.pr_text)" + }, + "posts": { + "nano_foundation": "ナノ財団", + "top": "トップ", + "trending": "トレンド" + }, + "representative_alerts": { + "table_header": { + "behind": "遅れ", + "issue": "問題", + "last_online": "最終オンライン", + "percent_online_weight": "オンライン重量の%", + "representative": "代表者" + }, + "tooltip": { + "behind": "代表者が遅れているか、ブートストラッピングしています。カットオフは95パーセンタイルを超えるセメントカウントです。(テレメトリ経由)", + "low_uptime": "代表者が過去28日間で25%以上オフラインでした。", + "offline": "代表者が投票を停止し、オフラインのようです。", + "overweight": "代表者が3Mナノ以上の投票重量を持っています。委任者は重量を分散してネットワークの回復力と価値を向上させることを検討する必要があります。" + }, + "type": { + "behind": "遅れ", + "low_uptime": "低稼働時間", + "offline": "オフライン", + "overweight": "過重" + } + }, + "representatives_cemented_by_weight": { + "title": "確認差異", + "tooltip": "リーディングノードからの確認数X以内にある投票重量の量を表示します。ネットワーク全体でノードがどれだけ同期していて整列しているかを知るのに役立ちます" + }, + "representatives_checked_by_weight": { + "title": "ブロック差異", + "tooltip": "リーディングノードからのブロック数X以内にある投票重量の量を表示します。ネットワーク内でブロック伝播がどれだけ同期しているかを感じるのに役立ちます" + }, + "representative_delegators": { + "showing_top_delegators": "最小残高1ナノを持つトップ100の委任者を表示しています。" + }, + "representative_info": { + "first_seen": "最初に見た", + "last_seen": "最後に見た", + "weight_represented": "表される重量" + }, + "representative_network": { + "city": "市", + "isp": "ISP", + "network": "ネットワーク", + "provider": "プロバイダー" + }, + "representative_telemetry": { + "telemetry": "テレメトリ", + "telemetry_timestamp": "テレメトリタイムスタンプ" + }, + "representative_uptime": { + "2m_uptime": "2ヶ月稼働時間", + "2w_uptime": "2週間稼働時間", + "3m_uptime": "3ヶ月稼働時間", + "current_status": "現在のステータス", + "down": "ダウン", + "down_for": "ダウン期間", + "operational": "運用中", + "up_for": "アップ期間", + "warning": "警告" + }, + "representatives": { + "alias": "エイリアス", + "cpu_cores": "CPUコア", + "cpu_model": "CPUモデル", + "tdp": "TDP (wH)", + "protocol_version": "プロトコル", + "last_seen": "最後に見た", + "host_asn": "ホストASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "各ノードによってローカルで設定された帯域幅制限に基づいた投票重量の量を表示します" + }, + "representatives_country_by_weight": { + "title": "国" + }, + "representatives_offline": { + "account": "オフラインアカウント", + "last_online": "最後のオンライン" + }, + "representatives_page": { + "seo_description": "Nanoネットワークの代表者を探索し分析する", + "seo_title": "Nano代表者エクスプローラー", + "telemetry_tab": "テレメトリ", + "weight_distribution_tab": "重量分布", + "weight_history_tab": "重量履歴", + "offline_reps_tab": "オフライン代表者" + }, + "representatives_provider_by_weight": { + "title": "ホスティングプロバイダー" + }, + "representatives_quorum_charts": { + "peers_weight": "ピアの重量", + "quorum_delta": "クォーラムデルタ", + "title": "クォーラムチャート", + "trended_weight": "トレンド重量" + }, + "representatives_search": { + "placeholder": "アカウント、エイリアス、IPでフィルター" + }, + "representatives_weight": { + "trended": "トレンド" + }, + "representatives_weight_chart": { + "title": "代表者による重量分布" + }, + "representatives_version_by_weight": { + "title": "バージョン" + }, + "roadmap": { + "header": { + "subtitle": "コミュニティの目標", + "title": "計画" + }, + "seo": { + "description": "Nanoの開発とコミュニティのロードマップ", + "tags": [ + "ロードマップ", + "ナノ", + "未来", + "リリース", + "デザイン", + "タスク", + "議論", + "コミュニティ", + "大使", + "マネージャー" + ], + "title": "ロードマップ" + } + }, + "search_bar": { + "placeholder": "アドレス/ブロックハッシュで検索" + }, + "uptime": { + "now": "現在", + "days_ago": "日前" + } +} diff --git a/locales/ko.json b/locales/ko.json new file mode 100644 index 00000000..2924f99d --- /dev/null +++ b/locales/ko.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "계정 주소", + "change_summary": "요약 변경", + "copy_notification": "계정 주소가 복사되었습니다", + "seo_description": "나노 대표 정보", + "seo_title": "나노 계정", + "telemetry_charts": "텔레메트리 차트", + "unopened_description": "계정 주소가 유효하지만, 아직 블록이 관찰되지 않았습니다. 이 계정으로 NANO가 전송된 경우, 해당 블록을 게시하여 자금을 받고 개시 잔액을 설정해야 합니다. 계정의 잔액은 계정 소유자만이 자신의 체인에 블록을 게시할 수 있으므로 계정 소유자만 업데이트할 수 있습니다.", + "unopened_note": "개시 블록이 이미 게시된 경우, 네트워크를 통해 퍼지고 nano.community 노드에 의해 관찰되기까지 몇 분 정도 걸릴 수 있습니다.", + "unopened_title": "이 계정은 아직 열리지 않았습니다" + }, + "account_blocks_summary": { + "first_timestamp": "첫 타임스탬프", + "last_timestamp": "마지막 타임스탬프", + "max_amount": "최대 금액", + "min_amount": "최소 금액", + "no_records": "기록 없음", + "receiving_account": "수신 계정", + "representative_account": "대표 계정", + "sending_account": "송신 계정", + "showing_top_10": "총 내림차순으로 상위 10개 계정 표시", + "transactions": "TXs" + }, + "account_meta": { + "account_info": "계정 정보", + "funding_account": "자금 계정", + "funding_timestamp": "자금 타임스탬프", + "height": "높이", + "last_modified": "마지막 수정", + "open_timestamp": "개시 타임스탬프", + "opening_balance": "개시 잔액", + "receivable_balance": "수령 가능 잔액" + }, + "block_page": { + "amount": "금액", + "copy_notification": "블록 해시가 복사되었습니다", + "delegated_representative": "위임된 대표", + "description": "설명", + "epoch_v1": "에포크 v1 - 레거시 블록(오픈, 수신, 송신, 변경)에서 상태 블록으로 계정 체인을 업그레이드했습니다.", + "epoch_v2": "에포크 v2 - 더 높은 작업 증명 난이도를 사용하도록 계정 체인을 업그레이드했습니다.", + "receiving_account": "수신 계정", + "section_label": "블록 해시", + "sending_account": "송신 계정", + "seo_description": "나노 블록 관련 정보", + "seo_title": "나노 블록", + "voting_weight": "투표 무게" + }, + "block_info": { + "block_account": "블록 계정", + "operation": "작업", + "status": "상태", + "timestamp": "타임스탬프" + }, + "block_status": { + "confirmed": "확인됨", + "unconfirmed": "미확인" + }, + "block_type": { + "change": "변경", + "epoch": "에포크", + "open": "오픈", + "receive": "수신", + "send": "송신" + }, + "common": { + "account_one": "계정", + "account_other": "계정들", + "address": "주소", + "balance": "잔액", + "bandwidth_limit": "대역폭 제한", + "bandwidth_limit_short": "BW 제한", + "blocks": "블록", + "blocks_behind": "블록 뒤", + "blocks_diff_short": "블록 차이", + "by_online_weight": "온라인 무게로", + "clear_filters": "필터 지우기", + "click_to_copy": "복사하려면 클릭", + "collapse": "접기", + "conf_short": "확인.", + "conf_diff_short": "확인 차이", + "confirmations_behind": "확인 뒤", + "country": "국가", + "delegator_one": "위임자", + "delegator_other": "위임자들", + "max": "최대", + "min": "최소", + "offline": "오프라인", + "online": "온라인", + "peers": "피어", + "percent_of_total": "총 %", + "port": "포트", + "quorum_delta": "쿼럼 델타", + "representative_one": "대표", + "representative_other": "대표들", + "show_more": "{{count}}개 더 보기", + "total": "총계", + "unchecked": "미확인", + "unchecked_count": "미확인 수", + "unlimited": "무제한", + "uptime": "가동 시간", + "version": "버전", + "weight": "무게" + }, + "delegators": { + "showing_top_delegators": "최소 1 나노의 최소 잔액을 가진 상위 100명의 위임자 표시." + }, + "doc": { + "contributors": "기여자", + "document_not_found": "문서(또는 계정)을 찾을 수 없습니다", + "edit_page": "페이지 편집", + "help_out": "도움말", + "not_found_404": "404", + "section_link_copied": "섹션 링크가 복사되었습니다", + "updated_by": "업데이트됨" + }, + "github_events": { + "action": { + "added_member": "멤버 추가됨", + "commented_on_commit": "커밋에 대한 코멘트", + "commented_on_issue": "이슈에 대한 코멘트", + "commented_on_pr_review": "PR 리뷰에 대한 코멘트", + "created": "{{action}} 생성됨", + "deleted": "{{action}} 삭제됨", + "forked": "포크됨", + "issue_action": "{{action}} 이슈", + "made_public": "공개됨", + "pr_action": "{{action}} PR", + "pr_review": "PR 리뷰 {{title}}", + "published_release": "릴리스 게시됨", + "pushed_commit": "{{ref}}에 커밋 푸시됨", + "sponsorship_started": "후원 시작됨", + "watching_repo": "저장소를 보고 있음" + }, + "events_title": "개발 이벤트" + }, + "ledger": { + "addresses": { + "active_detail": "활성은 사용된 고유 주소의 수를 보여줍니다. 새로운 것은 생성된 주소의 수를 보여줍니다. 재사용된 것은 이전 날에 생성된 주소가 사용된 수를 보여줍니다.", + "active_stats": "활성 주소 통계", + "new_stats": "새 주소 통계", + "total_number": "일일 활성, 새로운, 재사용된 주소의 총 수." + }, + "amounts": { + "total_number": "블록의 금액이 주어진 범위(나노 단위)에 있는 하루에 확인된 송신 유형 블록의 수" + }, + "blocks": { + "change": "변경 블록 통계", + "description": "하루에 확인된 블록의 수.", + "open": "오픈 블록 통계", + "receive": "수신 블록 통계", + "send": "송신 블록 통계", + "total": "총 블록 통계" + }, + "description": "설명", + "usd_transferred": { + "desc_1": "하루에 전송된 총 가치(USD 단위).", + "desc_2": "Nano/USD의 일일 종가와 그날 전송된 총 나노 양을 기준으로 합니다.", + "usd_transferred": "USD로 전송됨", + "usd_transferred_stats": "USD 전송 통계" + }, + "volume": { + "change_stats": "변경 통계", + "description": "하루에 전송된 총 금액(나노 단위)과 투표 무게가 변경된 총 금액.", + "send_stats": "송신 통계" + } + }, + "ledger_page": { + "addresses_tab": "주소", + "amounts_tab": "금액", + "blocks_tab": "블록", + "seo_description": "나노 원장의 온체인 메트릭스 및 분석", + "seo_title": "나노 원장 분석", + "value_transferred_tab": "전송된 가치", + "volume_tab": "볼륨" + }, + "menu": { + "account_setup": "계정 설정", + "acquiring": "획득", + "advantages": "장점", + "attack_vectors": "공격 벡터", + "basics": "기본", + "best_practices": "최고의 관행", + "choosing_a_rep": "대표 선택", + "challenges": "도전", + "communities": "커뮤니티", + "contribution_guide": "기여 가이드", + "design": "디자인", + "developer_discussions": "개발자 토론", + "developers": "개발자", + "documentation": "문서", + "faqs": "FAQs", + "get_involved": "참여하기", + "get_support": "지원 받기", + "getting_started": "시작하기", + "glossary": "용어집", + "guides": "가이드", + "history": "역사", + "home": "홈", + "how_it_works": "작동 원리", + "integrations": "통합", + "introduction": "소개", + "investment_thesis": "투자 논문", + "learn": "배우기", + "ledger": "원장", + "misconceptions": "오해", + "overview": "개요", + "planning": "계획", + "privacy": "개인 정보 보호", + "protocol": "프로토콜", + "running_a_node": "노드 운영", + "security": "보안", + "stats": "통계", + "storing": "저장", + "telemetry": "텔레메트리", + "topics": "주제", + "using": "사용", + "why_it_matters": "중요한 이유" + }, + "network": { + "backlog_text": "확인을 기다리는 트랜잭션의 중간 수 $(network.pr_text)", + "censor_text": "트랜잭션을 검열하거나 네트워크를 정지시키기 위해 필요한 대표의 최소 수", + "confirm_text": "트랜잭션을 확인하기 위해 필요한 대표의 최소 수", + "confirmations": "확인 (24시간)", + "confirmations_text": "지난 24시간 동안 네트워크가 확인한 트랜잭션의 총 수", + "energy_text": "수집된 CPU 모델 정보를 기반으로 한 주요 대표의 추정 실시간 네트워크 CPU 에너지 사용량입니다. 이 추정치는 모든 코어가 제조업체가 정의한 고복잡도 작업 부하에서 기본 주파수로 작동할 때 프로세서가 발산하는 평균 전력(와트)인 CPU TDP를 기반으로 합니다.", + "energy_usage": "에너지 사용량 (TDP) (24시간)", + "fee_text": "나노 네트워크는 수수료 없이 운영됩니다", + "nano_ticker": "나노티커", + "online_stake": "온라인 스테이크", + "principal_reps": "주요 대표", + "pr_text": "온라인 투표 무게의 0.1% 이상이 위임된 투표 노드인 네트워크의 주요 대표를 통해 관찰됩니다", + "reps_to_censor": "검열 또는 정지를 위한 대표", + "reps_to_confirm": "확인을 위한 대표", + "settlement": "결제 (24시간)", + "settlement_text": "지난 24시간 동안 네트워크가 결제한 총 가치", + "speed_text": "테스트 트랜잭션이 확인될 때까지의 밀리초 시간", + "stake_text": "투표에 적극적으로 참여하는 위임된 나노 무게의 백분율", + "stats_title": "네트워크 통계", + "total_reps": "총 대표 (24시간)", + "tx_backlog": "트랜잭션 백로그", + "tx_fees": "트랜잭션 수수료 (24시간)", + "tx_speed": "트랜잭션 속도", + "tx_throughput": "트랜잭션 처리량", + "throughput_text": "지난 분 동안 초당 확인된 트랜잭션의 중앙값 $(network.pr_text)" + }, + "posts": { + "nano_foundation": "나노 재단", + "top": "상위", + "trending": "인기" + }, + "representative_alerts": { + "table_header": { + "behind": "지연", + "issue": "문제", + "last_online": "마지막 온라인", + "percent_online_weight": "% 온라인 무게", + "representative": "대표" + }, + "tooltip": { + "behind": "대표가 지연되었거나 부트스트래핑 중입니다. 기준은 95번째 백분위수를 넘는 시멘트 수입니다. (텔레메트리를 통해)", + "low_uptime": "대표가 지난 28일 동안 25% 이상 오프라인 상태였습니다.", + "offline": "대표가 투표를 중단하고 오프라인으로 보입니다.", + "overweight": "대표가 3M 나노 이상의 투표 무게를 가지고 있습니다. 위임자는 네트워크의 회복력과 가치를 향상시키기 위해 무게를 분배하는 것을 고려해야 합니다." + }, + "type": { + "behind": "지연", + "low_uptime": "낮은 가동 시간", + "offline": "오프라인", + "overweight": "과중" + } + }, + "representatives_cemented_by_weight": { + "title": "확인 차이", + "tooltip": "선두 노드로부터 X 번호의 확인 내에 있는 투표 무게의 양을 표시합니다. 네트워크 전반에 걸쳐 노드가 얼마나 잘 동기화되고 정렬되어 있는지 알 수 있습니다." + }, + "representatives_checked_by_weight": { + "title": "블록 차이", + "tooltip": "선두 노드로부터 X 번호의 블록 내에 있는 투표 무게의 양을 표시합니다. 네트워크 내에서 블록 전파가 얼마나 동기화되어 있는지 감을 얻는 데 유용합니다." + }, + "representative_delegators": { + "showing_top_delegators": "최소 잔액 1 나노를 가진 상위 100명의 위임자를 표시합니다." + }, + "representative_info": { + "first_seen": "처음 발견됨", + "last_seen": "마지막으로 발견됨", + "weight_represented": "대표 무게" + }, + "representative_network": { + "city": "도시", + "isp": "ISP", + "network": "네트워크", + "provider": "제공자" + }, + "representative_telemetry": { + "telemetry": "텔레메트리", + "telemetry_timestamp": "텔레메트리 타임스탬프" + }, + "representative_uptime": { + "2m_uptime": "2M 가동 시간", + "2w_uptime": "2주 가동 시간", + "3m_uptime": "3M 가동 시간", + "current_status": "현재 상태", + "down": "다운", + "down_for": "다운 시간", + "operational": "운영 중", + "up_for": "가동 시간", + "warning": "경고" + }, + "representatives": { + "alias": "별칭", + "cpu_cores": "CPU 코어", + "cpu_model": "CPU 모델", + "tdp": "TDP (wH)", + "protocol_version": "프로토콜", + "last_seen": "마지막으로 발견됨", + "host_asn": "호스트 ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "각 노드가 로컬에서 설정한 대역폭 제한을 기반으로 한 투표 무게의 양을 표시합니다." + }, + "representatives_country_by_weight": { + "title": "국가" + }, + "representatives_offline": { + "account": "오프라인 계정", + "last_online": "마지막 온라인" + }, + "representatives_page": { + "seo_description": "나노 네트워크 대표를 탐색하고 분석합니다", + "seo_title": "나노 대표 탐색기", + "telemetry_tab": "텔레메트리", + "weight_distribution_tab": "무게 분포", + "weight_history_tab": "무게 역사", + "offline_reps_tab": "오프라인 대표" + }, + "representatives_provider_by_weight": { + "title": "호스팅 제공자" + }, + "representatives_quorum_charts": { + "peers_weight": "동료 무게", + "quorum_delta": "쿼럼 델타", + "title": "쿼럼 차트", + "trended_weight": "추세 무게" + }, + "representatives_search": { + "placeholder": "계정, 별칭, IP로 필터링" + }, + "representatives_weight": { + "trended": "추세" + }, + "representatives_weight_chart": { + "title": "대표별 무게 분포" + }, + "representatives_version_by_weight": { + "title": "버전" + }, + "roadmap": { + "header": { + "subtitle": "커뮤니티 목표", + "title": "계획" + }, + "seo": { + "description": "나노 개발 및 커뮤니티 로드맵", + "tags": [ + "로드맵", + "나노", + "미래", + "릴리스", + "디자인", + "작업", + "토론", + "커뮤니티", + "대사", + "매니저" + ], + "title": "로드맵" + } + }, + "search_bar": { + "placeholder": "주소 / 블록 해시로 검색" + }, + "uptime": { + "now": "지금", + "days_ago": "일 전" + } +} diff --git a/locales/nl.json b/locales/nl.json new file mode 100644 index 00000000..a4b0e44c --- /dev/null +++ b/locales/nl.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Accountadres", + "change_summary": "Samenvatting wijzigen", + "copy_notification": "Accountadres gekopieerd", + "seo_description": "Informatie voor nano vertegenwoordiger", + "seo_title": "Nano Account", + "telemetry_charts": "Telemetrie Grafieken", + "unopened_description": "Hoewel het accountadres geldig is, zijn er geen blokken waargenomen. Als NANO naar dit account is verzonden, moet het nog een overeenkomstig blok publiceren om de fondsen te ontvangen en een openingsbalans vast te stellen. Het saldo van een account kan alleen worden bijgewerkt door de accounthouder, omdat zij de enigen zijn die blokken op hun keten kunnen publiceren.", + "unopened_note": "Als er al een openingsblok is gepubliceerd, kan het even duren voordat het zich door het netwerk verspreidt en wordt waargenomen door de nano.community nodes.", + "unopened_title": "Dit account is nog niet geopend" + }, + "account_blocks_summary": { + "first_timestamp": "Eerste Tijdstempel", + "last_timestamp": "Laatste Tijdstempel", + "max_amount": "Max Bedrag", + "min_amount": "Min Bedrag", + "no_records": "Geen Records", + "receiving_account": "Ontvangend Account", + "representative_account": "Vertegenwoordigend Account", + "sending_account": "Verzendend Account", + "showing_top_10": "Toont top 10 accounts op totaal aflopend", + "transactions": "Transacties" + }, + "account_meta": { + "account_info": "Accountinformatie", + "funding_account": "Financieringsaccount", + "funding_timestamp": "Financieringstijdstempel", + "height": "Hoogte", + "last_modified": "Laatst Gewijzigd", + "open_timestamp": "Open Tijdstempel", + "opening_balance": "Openingsbalans", + "receivable_balance": "Te Ontvangen Balans" + }, + "block_page": { + "amount": "Bedrag", + "copy_notification": "Blokhash gekopieerd", + "delegated_representative": "Gedelegeerde Vertegenwoordiger", + "description": "Beschrijving", + "epoch_v1": "Epoch v1 — Geüpgrade accountketens van legacy blokken (open, ontvang, verzend, wijzig) naar staat blokken.", + "epoch_v2": "Epoch v2 - Geüpgrade accountketens om hogere Proof-of-Work moeilijkheid te gebruiken.", + "receiving_account": "Ontvangend Account", + "section_label": "Blok Hash", + "sending_account": "Verzendend Account", + "seo_description": "Informatie gerelateerd aan een Nano Blok", + "seo_title": "Nano Blok", + "voting_weight": "Stemgewicht" + }, + "block_info": { + "block_account": "Blok Account", + "operation": "Operatie", + "status": "Status", + "timestamp": "Tijdstempel" + }, + "block_status": { + "confirmed": "Bevestigd", + "unconfirmed": "Onbevestigd" + }, + "block_type": { + "change": "Wijzig", + "epoch": "Epoch", + "open": "Open", + "receive": "Ontvang", + "send": "Verzend" + }, + "common": { + "account_one": "Account", + "account_other": "Accounts", + "address": "Adres", + "balance": "Balans", + "bandwidth_limit": "Bandbreedtelimiet", + "bandwidth_limit_short": "BW Limiet", + "blocks": "Blokken", + "blocks_behind": "Blokken Achter", + "blocks_diff_short": "Blokken Versch.", + "by_online_weight": "Door Online Gewicht", + "clear_filters": "Filters Wissen", + "click_to_copy": "Klik om te kopiëren", + "collapse": "Inklappen", + "conf_short": "Bevest.", + "conf_diff_short": "Bevest. Versch.", + "confirmations_behind": "Bevestigingen Achter", + "country": "Land", + "delegator_one": "Delegator", + "delegator_other": "Delegators", + "max": "Max", + "min": "Min", + "offline": "Offline", + "online": "Online", + "peers": "Peers", + "percent_of_total": "% van Totaal", + "port": "Poort", + "quorum_delta": "Quorum Delta", + "representative_one": "Vertegenwoordiger", + "representative_other": "Vertegenwoordigers", + "show_more": "Toon {{count}} meer", + "total": "Totaal", + "unchecked": "Ongecontroleerd", + "unchecked_count": "Ongecontroleerd Aantal", + "unlimited": "Onbeperkt", + "uptime": "Uptime", + "version": "Versie", + "weight": "Gewicht" + }, + "delegators": { + "showing_top_delegators": "Toont de top 100 delegators met een minimum saldo van 1 Nano." + }, + "doc": { + "contributors": "Bijdragers", + "document_not_found": "Document (of Account) niet gevonden", + "edit_page": "Pagina bewerken", + "help_out": "Helpen", + "not_found_404": "404", + "section_link_copied": "Sectielink gekopieerd", + "updated_by": "bijgewerkt door" + }, + "github_events": { + "action": { + "added_member": "lid toegevoegd", + "commented_on_commit": "gereageerd op commit", + "commented_on_issue": "gereageerd op issue", + "commented_on_pr_review": "gereageerd op pr review", + "created": "aangemaakt {{action}}", + "deleted": "verwijderd {{action}}", + "forked": "geforkt", + "issue_action": "{{action}} issue", + "made_public": "openbaar gemaakt", + "pr_action": "{{action}} pr", + "pr_review": "pr review {{title}}", + "published_release": "publicatie uitgebracht", + "pushed_commit": "commit gepusht naar {{ref}}", + "sponsorship_started": "sponsoring gestart", + "watching_repo": "repo volgen" + }, + "events_title": "Ontwikkelingsevenementen" + }, + "ledger": { + "addresses": { + "active_detail": "Actief toont het aantal unieke adressen dat gebruikt is. Nieuw toont het aantal adressen dat gecreëerd is. Hergebruikt toont het aantal adressen dat gebruikt is dat op een eerdere dag gecreëerd werd.", + "active_stats": "Actieve Adresstatistieken", + "new_stats": "Nieuwe Adresstatistieken", + "total_number": "Het totale aantal actieve, nieuwe en hergebruikte adressen dat per dag gebruikt wordt." + }, + "amounts": { + "total_number": "Het aantal bevestigde verzend-type blokken per dag waarbij het bedrag in het blok binnen een bepaald bereik valt (in Nano)" + }, + "blocks": { + "change": "Wijzigingsblok Statistieken", + "description": "Het aantal blokken bevestigd per dag.", + "open": "Openingsblok Statistieken", + "receive": "Ontvangstblok Statistieken", + "send": "Verzendblok Statistieken", + "total": "Totale Blokstatistieken" + }, + "description": "Beschrijving", + "usd_transferred": { + "desc_1": "Het totale bedrag aan waarde overgedragen (in USD) per dag.", + "desc_2": "Gebaseerd op de dagelijkse slotkoers van Nano/USD en het totale bedrag aan Nano overgedragen die dag.", + "usd_transferred": "USD Overgedragen", + "usd_transferred_stats": "USD Overgedragen Statistieken" + }, + "volume": { + "change_stats": "Wijzigingsstatistieken", + "description": "Het totale verzonden bedrag (in Nano) en het totale bedrag aan stemgewicht gewijzigd per dag.", + "send_stats": "Verzendstatistieken" + } + }, + "ledger_page": { + "addresses_tab": "Adressen", + "amounts_tab": "Bedragen", + "blocks_tab": "Blokken", + "seo_description": "On-chain metrieken en analyses van het Nano grootboek", + "seo_title": "Nano Grootboek Analyse", + "value_transferred_tab": "Overgedragen Waarde", + "volume_tab": "Volume" + }, + "menu": { + "account_setup": "Account Instellen", + "acquiring": "Verkrijgen", + "advantages": "Voordelen", + "attack_vectors": "Aanvalsvectoren", + "basics": "Basis", + "best_practices": "Beste Praktijken", + "choosing_a_rep": "Een vertegenwoordiger kiezen", + "challenges": "Uitdagingen", + "communities": "Gemeenschappen", + "contribution_guide": "Bijdragegids", + "design": "Ontwerp", + "developer_discussions": "Ontwikkelaarsdiscussies", + "developers": "Ontwikkelaars", + "documentation": "Documentatie", + "faqs": "FAQs", + "get_involved": "Doe mee", + "get_support": "Ondersteuning krijgen", + "getting_started": "Beginnen", + "glossary": "Woordenlijst", + "guides": "Gidsen", + "history": "Geschiedenis", + "home": "Home", + "how_it_works": "Hoe het werkt", + "integrations": "Integraties", + "introduction": "Introductie", + "investment_thesis": "Investeringsthese", + "learn": "Leren", + "ledger": "Grootboek", + "misconceptions": "Misvattingen", + "overview": "Overzicht", + "planning": "Planning 👾", + "privacy": "Privacy", + "protocol": "Protocol", + "running_a_node": "Een node uitvoeren", + "security": "Beveiliging", + "stats": "Statistieken", + "storing": "Opslaan", + "telemetry": "Telemetrie", + "topics": "Onderwerpen", + "using": "Gebruiken", + "why_it_matters": "Waarom het belangrijk is" + }, + "network": { + "backlog_text": "Mediaan aantal transacties wachtend op bevestiging $(network.pr_text)", + "censor_text": "Het minimum aantal vertegenwoordigers nodig om transacties te censureren of het netwerk te stagneren", + "confirm_text": "Het minimum aantal vertegenwoordigers nodig om transacties te bevestigen", + "confirmations": "Bevestigingen (24u)", + "confirmations_text": "Totaal aantal transacties bevestigd door het netwerk in de laatste 24 uur", + "energy_text": "Geschat live netwerk CPU energieverbruik van Principiële Vertegenwoordigers gebaseerd op verzamelde CPU model info. De schatting is gebaseerd op CPU TDP, wat het gemiddelde vermogen, in watt, is dat de processor afgeeft bij bedrijf op basisfrequentie met alle kernen actief onder door de fabrikant gedefinieerde, hoog-complexiteit werklast", + "energy_usage": "Energieverbruik (TDP) (24u)", + "fee_text": "Het Nano netwerk werkt zonder kosten", + "nano_ticker": "NanoTicker", + "online_stake": "Online Inzet", + "principal_reps": "Principiële Vertegenwoordigers", + "pr_text": "zoals waargenomen over de netwerken principiële vertegenwoordigers: stemmende nodes met meer dan 0.1% van het online stemgewicht aan hen gedelegeerd", + "reps_to_censor": "Vertegenwoordigers om te Censureren of Stagneren", + "reps_to_confirm": "Vertegenwoordigers om te Bevestigen", + "settlement": "Afhandeling (24u)", + "settlement_text": "Totaal bedrag aan waarde afgewikkeld door het netwerk over de laatste 24 uur", + "speed_text": "Tijd in milliseconden voor een testtransactie om bevestigd te worden", + "stake_text": "Percentage van gedelegeerd Nano gewicht actief deelnemend in stemmen", + "stats_title": "Netwerkstatistieken", + "total_reps": "Totaal Vertegenwoordigers (24u)", + "tx_backlog": "Tx Achterstand", + "tx_fees": "Tx Kosten (24u)", + "tx_speed": "Tx Snelheid", + "tx_throughput": "Tx Doorvoer", + "throughput_text": "Mediaan aantal transacties bevestigd per seconde in de laatste minuut $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano Stichting", + "top": "Top", + "trending": "Trending" + }, + "representative_alerts": { + "table_header": { + "behind": "Achter", + "issue": "Probleem", + "last_online": "Laatst Online", + "percent_online_weight": "% Online Gewicht", + "representative": "Vertegenwoordiger" + }, + "tooltip": { + "behind": "Vertegenwoordiger is achtergebleven of is aan het opstarten. De afkap is een gecementeerd aantal voorbij de 95e percentiel. (via telemetrie)", + "low_uptime": "Vertegenwoordiger is meer dan 25% offline geweest in de laatste 28 dagen.", + "offline": "Vertegenwoordiger is gestopt met stemmen en lijkt offline.", + "overweight": "Vertegenwoordiger heeft meer dan 3M Nano stemgewicht. Delegators zouden moeten overwegen het gewicht te verdelen om de veerkracht en waarde van het netwerk te verbeteren." + }, + "type": { + "behind": "Achter", + "low_uptime": "Lage Uptime", + "offline": "Offline", + "overweight": "Overgewicht" + } + }, + "representatives_cemented_by_weight": { + "title": "Bevestigingsverschil", + "tooltip": "Toont de hoeveelheid stemgewicht die binnen X aantal bevestigingen van de leidende node is. Handig om te weten hoe goed gesynchroniseerd en uitgelijnd nodes zijn over het netwerk" + }, + "representatives_checked_by_weight": { + "title": "Blokverschil", + "tooltip": "Toont de hoeveelheid stemgewicht die binnen X aantal blokken van de leidende node is. Nuttig om een gevoel te krijgen van hoe goed blokpropagatie is gesynchroniseerd binnen het netwerk" + }, + "representative_delegators": { + "showing_top_delegators": "Toont top 100 delegators met een minimum saldo van 1 Nano." + }, + "representative_info": { + "first_seen": "Eerst Gezien", + "last_seen": "Laatst Gezien", + "weight_represented": "Gewicht Vertegenwoordigd" + }, + "representative_network": { + "city": "Stad", + "isp": "ISP", + "network": "Netwerk", + "provider": "Provider" + }, + "representative_telemetry": { + "telemetry": "Telemetrie", + "telemetry_timestamp": "Telemetrie Tijdstempel" + }, + "representative_uptime": { + "2m_uptime": "2M Uptime", + "2w_uptime": "2W Uptime", + "3m_uptime": "3M Uptime", + "current_status": "Huidige Status", + "down": "Omlaag", + "down_for": "Omlaag Voor", + "operational": "Operationeel", + "up_for": "Omhoog Voor", + "warning": "Waarschuwing" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "CPU Kernen", + "cpu_model": "CPU Model", + "tdp": "TDP (wH)", + "protocol_version": "Protocol", + "last_seen": "Laatst Gezien", + "host_asn": "Host ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Toont de hoeveelheid stemgewicht gebaseerd op de bandbreedtelimiet die lokaal door elke node is ingesteld" + }, + "representatives_country_by_weight": { + "title": "Land" + }, + "representatives_offline": { + "account": "Offline Account", + "last_online": "Laatst Online" + }, + "representatives_page": { + "seo_description": "Verken en analyseer Nano netwerkvertegenwoordigers", + "seo_title": "Nano Verteegenwoordigers Verkenner", + "telemetry_tab": "Telemetrie", + "weight_distribution_tab": "Gewichtsverdeling", + "weight_history_tab": "Gewichtsgeschiedenis", + "offline_reps_tab": "Offline Vertegenwoordigers" + }, + "representatives_provider_by_weight": { + "title": "Hosting Provider" + }, + "representatives_quorum_charts": { + "peers_weight": "Peers Gewicht", + "quorum_delta": "Quorum Delta", + "title": "Quorum Grafieken", + "trended_weight": "Getrend Gewicht" + }, + "representatives_search": { + "placeholder": "Filter op account, alias, ip" + }, + "representatives_weight": { + "trended": "Getrend" + }, + "representatives_weight_chart": { + "title": "Gewichtsverdeling per Vertegenwoordiger" + }, + "representatives_version_by_weight": { + "title": "Versies" + }, + "roadmap": { + "header": { + "subtitle": "Gemeenschapsdoelstellingen", + "title": "Planning" + }, + "seo": { + "description": "Nano ontwikkeling & gemeenschapsroadmap", + "tags": [ + "roadmap", + "nano", + "toekomst", + "release", + "ontwerp", + "taken", + "discussies", + "gemeenschap", + "ambassadeurs", + "managers" + ], + "title": "Roadmap" + } + }, + "search_bar": { + "placeholder": "Zoeken op Adres / Blok Hash" + }, + "uptime": { + "now": "Nu", + "days_ago": "dagen geleden" + } +} diff --git a/locales/no.json b/locales/no.json new file mode 100644 index 00000000..487d407d --- /dev/null +++ b/locales/no.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Kontoadresse", + "change_summary": "Endringssammendrag", + "copy_notification": "Kontoadresse kopiert", + "seo_description": "Informasjon for nano-representant", + "seo_title": "Nano-konto", + "telemetry_charts": "Telemetridiagrammer", + "unopened_description": "Selv om kontoadressen er gyldig, har ingen blokker blitt observert. Hvis NANO er sendt til denne kontoen, må det fortsatt publiseres en tilsvarende blokk for å motta midlene og etablere en åpningsbalanse. En kontos saldo kan kun oppdateres av kontoinnehaveren, da de er de eneste som kan publisere blokker til sin kjede.", + "unopened_note": "Hvis en åpningsblokk allerede er publisert, kan det ta noen øyeblikk å spre seg gjennom nettverket og bli observert av nano.community-nodene.", + "unopened_title": "Denne kontoen har ikke blitt åpnet ennå" + }, + "account_blocks_summary": { + "first_timestamp": "Første tidsstempel", + "last_timestamp": "Siste tidsstempel", + "max_amount": "Maks beløp", + "min_amount": "Min beløp", + "no_records": "Ingen poster", + "receiving_account": "Mottakende konto", + "representative_account": "Representantkonto", + "sending_account": "Senderkonto", + "showing_top_10": "Viser topp 10 kontoer etter totalt synkende", + "transactions": "Transaksjoner" + }, + "account_meta": { + "account_info": "Kontoinformasjon", + "funding_account": "Finansieringskonto", + "funding_timestamp": "Finansieringstidsstempel", + "height": "Høyde", + "last_modified": "Sist endret", + "open_timestamp": "Åpningstidsstempel", + "opening_balance": "Åpningsbalanse", + "receivable_balance": "Mottakelig saldo" + }, + "block_page": { + "amount": "Beløp", + "copy_notification": "Blokkhash kopiert", + "delegated_representative": "Delegert representant", + "description": "Beskrivelse", + "epoch_v1": "Epoche v1 - Oppgraderte konto-kjeder fra legacy blokker (åpen, motta, sende, endre) til tilstands blokker.", + "epoch_v2": "Epoche v2 - Oppgraderte konto-kjeder for å bruke høyere Proof-of-Work vanskelighetsgrad.", + "receiving_account": "Mottakende konto", + "section_label": "Blokkhash", + "sending_account": "Senderkonto", + "seo_description": "Informasjon relatert til en Nano-blokk", + "seo_title": "Nano-blokk", + "voting_weight": "Stemmevekt" + }, + "block_info": { + "block_account": "Blokkkonto", + "operation": "Operasjon", + "status": "Status", + "timestamp": "Tidsstempel" + }, + "block_status": { + "confirmed": "Bekreftet", + "unconfirmed": "Ubekreftet" + }, + "block_type": { + "change": "Endre", + "epoch": "Epoche", + "open": "Åpen", + "receive": "Motta", + "send": "Sende" + }, + "common": { + "account_one": "Konto", + "account_other": "Kontoer", + "address": "Adresse", + "balance": "Saldo", + "bandwidth_limit": "Båndbreddegrense", + "bandwidth_limit_short": "BW-grense", + "blocks": "Blokker", + "blocks_behind": "Blokker bak", + "blocks_diff_short": "Blokker Diff", + "by_online_weight": "Etter online vekt", + "clear_filters": "Fjern filtre", + "click_to_copy": "Klikk for å kopiere", + "collapse": "Kollaps", + "conf_short": "Bekr.", + "conf_diff_short": "Bekr. Diff", + "confirmations_behind": "Bekreftelser bak", + "country": "Land", + "delegator_one": "Delegator", + "delegator_other": "Delegatorer", + "max": "Maks", + "min": "Min", + "offline": "Frakoblet", + "online": "På nett", + "peers": "Likemenn", + "percent_of_total": "% av total", + "port": "Port", + "quorum_delta": "Kvorum Delta", + "representative_one": "Representant", + "representative_other": "Representanter", + "show_more": "Vis {{count}} mer", + "total": "Total", + "unchecked": "Ukontrollert", + "unchecked_count": "Ukontrollert Antall", + "unlimited": "Ubegrenset", + "uptime": "Oppetid", + "version": "Versjon", + "weight": "Vekt" + }, + "delegators": { + "showing_top_delegators": "Viser topp 100 delegatorer med en minimumssaldo på 1 Nano." + }, + "doc": { + "contributors": "Bidragsytere", + "document_not_found": "Dokument (eller konto) ikke funnet", + "edit_page": "Rediger side", + "help_out": "Hjelp til", + "not_found_404": "404", + "section_link_copied": "Seksjonslenke kopiert", + "updated_by": "oppdatert av" + }, + "github_events": { + "action": { + "added_member": "la til medlem", + "commented_on_commit": "kommenterte på commit", + "commented_on_issue": "kommenterte på problem", + "commented_on_pr_review": "kommenterte på PR-gjennomgang", + "created": "opprettet {{action}}", + "deleted": "slettet {{action}}", + "forked": "forket", + "issue_action": "{{action}} problem", + "made_public": "gjort offentlig", + "pr_action": "{{action}} PR", + "pr_review": "PR-gjennomgang {{title}}", + "published_release": "publisert utgivelse", + "pushed_commit": "pushet commit til {{ref}}", + "sponsorship_started": "sponsorat startet", + "watching_repo": "ser på repo" + }, + "events_title": "Utviklingshendelser" + }, + "ledger": { + "addresses": { + "active_detail": "Aktiv viser antall unike adresser brukt. Ny viser antall adresser opprettet. Gjenbrukt viser antall adresser brukt som ble opprettet på en tidligere dag.", + "active_stats": "Aktive adresser statistikk", + "new_stats": "Nye adresser statistikk", + "total_number": "Det totale antallet aktive, nye og gjenbrukte adresser brukt per dag." + }, + "amounts": { + "total_number": "Antall bekreftede sende-type blokker per dag der beløpet i blokken er innenfor et gitt område (i Nano)" + }, + "blocks": { + "change": "Endre blokkstatistikk", + "description": "Antall blokker bekreftet per dag.", + "open": "Åpne blokkstatistikk", + "receive": "Motta blokkstatistikk", + "send": "Sende blokkstatistikk", + "total": "Total blokkstatistikk" + }, + "description": "Beskrivelse", + "usd_transferred": { + "desc_1": "Det totale beløpet av verdi overført (i USD) per dag.", + "desc_2": "Basert på den daglige sluttkursen av Nano/USD og det totale beløpet av Nano overført den dagen.", + "usd_transferred": "USD Overført", + "usd_transferred_stats": "USD Overført Statistikk" + }, + "volume": { + "change_stats": "Endre statistikk", + "description": "Det totale beløpet sendt (i Nano) og det totale beløpet av stemmevekt endret per dag.", + "send_stats": "Sende statistikk" + } + }, + "ledger_page": { + "addresses_tab": "Adresser", + "amounts_tab": "Beløp", + "blocks_tab": "Blokker", + "seo_description": "Kjede-metrikker og analyser av Nano-ledgeren", + "seo_title": "Nano Ledger Analyse", + "value_transferred_tab": "Verdi Overført", + "volume_tab": "Volum" + }, + "menu": { + "account_setup": "Kontooppsett", + "acquiring": "Anskaffelse", + "advantages": "Fordeler", + "attack_vectors": "Angrepsvektorer", + "basics": "Grunnleggende", + "best_practices": "Beste praksiser", + "choosing_a_rep": "Velge en representant", + "challenges": "Utfordringer", + "communities": "Samfunn", + "contribution_guide": "Bidragsveiledning", + "design": "Design", + "developer_discussions": "Utviklerdiskusjoner", + "developers": "Utviklere", + "documentation": "Dokumentasjon", + "faqs": "FAQs", + "get_involved": "Bli involvert", + "get_support": "Få støtte", + "getting_started": "Komme i gang", + "glossary": "Glossar", + "guides": "Guider", + "history": "Historie", + "home": "Hjem", + "how_it_works": "Hvordan det fungerer", + "integrations": "Integrasjoner", + "introduction": "Introduksjon", + "investment_thesis": "Investeringsoppgave", + "learn": "Lær", + "ledger": "Hovedbok", + "misconceptions": "Misforståelser", + "overview": "Oversikt", + "planning": "Planlegging 👾", + "privacy": "Personvern", + "protocol": "Protokoll", + "running_a_node": "Kjøre en node", + "security": "Sikkerhet", + "stats": "Statistikk", + "storing": "Lagring", + "telemetry": "Telemetri", + "topics": "Temaer", + "using": "Bruke", + "why_it_matters": "Hvorfor det betyr noe" + }, + "network": { + "backlog_text": "Median antall transaksjoner som venter på å bli bekreftet $(network.pr_text)", + "censor_text": "Minimum antall representanter som trengs for å sensurere transaksjoner eller stoppe nettverket", + "confirm_text": "Minimum antall representanter som trengs for å bekrefte transaksjoner", + "confirmations": "Bekreftelser (24t)", + "confirmations_text": "Totalt antall transaksjoner bekreftet av nettverket i løpet av de siste 24 timene", + "energy_text": "Estimert live nettverks CPU energibruk av hovedrepresentanter basert på samlet CPU modellinfo. Estimatet er basert på CPU TDP, som er gjennomsnittlig kraft, i watt, prosessoren avgir når den opererer ved basisfrekvens med alle kjerner aktive under produsentdefinert, høykompleks arbeidsbelastning", + "energy_usage": "Energiforbruk (TDP) (24t)", + "fee_text": "Nano-nettverket opererer uten gebyrer", + "nano_ticker": "NanoTicker", + "online_stake": "Online Innsats", + "principal_reps": "Hovedrepresentanter", + "pr_text": "som observert på tvers av nettverkets hovedrepresentanter: stemmegivende noder med mer enn 0,1% av den online stemmevekten delegert til dem", + "reps_to_censor": "Reps for å sensurere eller stoppe", + "reps_to_confirm": "Reps for å bekrefte", + "settlement": "Oppgjør (24t)", + "settlement_text": "Total mengde verdi avgjort av nettverket i løpet av de siste 24 timene", + "speed_text": "Tid i millisekunder for en testtransaksjon for å bli bekreftet", + "stake_text": "Prosentandel av delegert Nano-vekt som aktivt deltar i avstemming", + "stats_title": "Nettverksstatistikk", + "total_reps": "Totalt Reps (24t)", + "tx_backlog": "Tx Venteliste", + "tx_fees": "Tx Gebyrer (24t)", + "tx_speed": "Tx Hastighet", + "tx_throughput": "Tx Gjennomstrømning", + "throughput_text": "Median antall transaksjoner bekreftet per sekund i det siste minuttet $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano Foundation", + "top": "Topp", + "trending": "Trender" + }, + "representative_alerts": { + "table_header": { + "behind": "Bak", + "issue": "Problem", + "last_online": "Sist Online", + "percent_online_weight": "% Online Vekt", + "representative": "Representant" + }, + "tooltip": { + "behind": "Representanten har falt bak eller er i oppstart. Grensen er en sementert telling utover det 95. persentil. (via telemetri)", + "low_uptime": "Representanten har vært offline mer enn 25% i løpet av de siste 28 dagene.", + "offline": "Representanten har sluttet å stemme og ser ut til å være offline.", + "overweight": "Representanten har utover 3M Nano stemmevekt. Delegatorer bør vurdere å distribuere vekten for å forbedre nettverkets motstandsdyktighet og verdi." + }, + "type": { + "behind": "Bak", + "low_uptime": "Lav Oppetid", + "offline": "Offline", + "overweight": "Overvektig" + } + }, + "representatives_cemented_by_weight": { + "title": "Bekreftelsesdifferensial", + "tooltip": "Viser mengden av stemmevekt som er innenfor X antall bekreftelser fra den ledende noden. Nyttig for å vite hvor godt synkroniserte og justerte nodene er på tvers av nettverket" + }, + "representatives_checked_by_weight": { + "title": "Blokker Differensial", + "tooltip": "Viser mengden av stemmevekt som er innenfor X antall blokker fra den ledende noden. Nyttig for å få en følelse av hvor synkronisert blokkpropagering er innen nettverket" + }, + "representative_delegators": { + "showing_top_delegators": "Viser topp 100 delegatorer med en minimumssaldo på 1 Nano." + }, + "representative_info": { + "first_seen": "Først Sett", + "last_seen": "Sist Sett", + "weight_represented": "Vekt Representert" + }, + "representative_network": { + "city": "By", + "isp": "ISP", + "network": "Nettverk", + "provider": "Leverandør" + }, + "representative_telemetry": { + "telemetry": "Telemetri", + "telemetry_timestamp": "Telemetri Tidsstempel" + }, + "representative_uptime": { + "2m_uptime": "2M Oppetid", + "2w_uptime": "2U Oppetid", + "3m_uptime": "3M Oppetid", + "current_status": "Nåværende Status", + "down": "Nede", + "down_for": "Nede For", + "operational": "Operativ", + "up_for": "Oppe For", + "warning": "Advarsel" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "CPU Kjerner", + "cpu_model": "CPU Modell", + "tdp": "TDP (wH)", + "protocol_version": "Protokoll", + "last_seen": "Sist Sett", + "host_asn": "Vert ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Viser mengden av stemmevekt basert på båndbreddegrensen satt lokalt av hver node" + }, + "representatives_country_by_weight": { + "title": "Land" + }, + "representatives_offline": { + "account": "Offline Konto", + "last_online": "Sist Online" + }, + "representatives_page": { + "seo_description": "Utforsk og analyser Nano-nettverkets representanter", + "seo_title": "Nano Representanter Utforsker", + "telemetry_tab": "Telemetri", + "weight_distribution_tab": "Vektfordeling", + "weight_history_tab": "Vekthistorikk", + "offline_reps_tab": "Offline Reps" + }, + "representatives_provider_by_weight": { + "title": "Hosting Leverandør" + }, + "representatives_quorum_charts": { + "peers_weight": "Jevevekt", + "quorum_delta": "Kvorum Delta", + "title": "Kvorum Diagrammer", + "trended_weight": "Trendet Vekt" + }, + "representatives_search": { + "placeholder": "Filtrer etter konto, alias, ip" + }, + "representatives_weight": { + "trended": "Trendet" + }, + "representatives_weight_chart": { + "title": "Vektfordeling etter Representant" + }, + "representatives_version_by_weight": { + "title": "Versjoner" + }, + "roadmap": { + "header": { + "subtitle": "Samfunnets mål", + "title": "Planlegging" + }, + "seo": { + "description": "Nano utvikling & samfunnsveikart", + "tags": [ + "veikart", + "nano", + "fremtid", + "utgivelse", + "design", + "oppgaver", + "diskusjoner", + "samfunn", + "ambassadører", + "ledere" + ], + "title": "Veikart" + } + }, + "search_bar": { + "placeholder": "Søk etter Adresse / Blokk Hash" + }, + "uptime": { + "now": "Nå", + "days_ago": "dager siden" + } +} diff --git a/locales/pl.json b/locales/pl.json new file mode 100644 index 00000000..a34d28ac --- /dev/null +++ b/locales/pl.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Adres konta", + "change_summary": "Podsumowanie zmian", + "copy_notification": "Skopiowano adres konta", + "seo_description": "Informacje dla przedstawiciela nano", + "seo_title": "Konto Nano", + "telemetry_charts": "Wykresy telemetrii", + "unopened_description": "Chociaż adres konta jest prawidłowy, nie zaobserwowano żadnych bloków. Jeśli NANO zostało wysłane na to konto, nadal musi opublikować odpowiadający blok, aby otrzymać środki i ustalić saldo otwarcia. Saldo konta może być aktualizowane tylko przez posiadacza konta, ponieważ tylko oni mogą publikować bloki na swoim łańcuchu.", + "unopened_note": "Jeśli blok otwierający został już opublikowany, może upłynąć kilka chwil, zanim rozprzestrzeni się on po sieci i zostanie zaobserwowany przez węzły nano.community.", + "unopened_title": "To konto nie zostało jeszcze otwarte" + }, + "account_blocks_summary": { + "first_timestamp": "Pierwszy znacznik czasu", + "last_timestamp": "Ostatni znacznik czasu", + "max_amount": "Maksymalna kwota", + "min_amount": "Minimalna kwota", + "no_records": "Brak rekordów", + "receiving_account": "Konto odbiorcze", + "representative_account": "Konto przedstawiciela", + "sending_account": "Konto nadawcze", + "showing_top_10": "Pokazuje 10 najlepszych kont według łącznej kwoty malejąco", + "transactions": "Transakcje" + }, + "account_meta": { + "account_info": "Informacje o koncie", + "funding_account": "Konto finansujące", + "funding_timestamp": "Znacznik czasu finansowania", + "height": "Wysokość", + "last_modified": "Ostatnia modyfikacja", + "open_timestamp": "Znacznik czasu otwarcia", + "opening_balance": "Saldo otwarcia", + "receivable_balance": "Saldo do odbioru" + }, + "block_page": { + "amount": "Kwota", + "copy_notification": "Skopiowano hash bloku", + "delegated_representative": "Delegowany przedstawiciel", + "description": "Opis", + "epoch_v1": "Epoka v1 — Ulepszenie łańcuchów kont z bloków dziedzicznych (otwarcie, odbiór, wysyłka, zmiana) do bloków stanu.", + "epoch_v2": "Epoka v2 - Ulepszenie łańcuchów kont do wykorzystania wyższej trudności Proof-of-Work.", + "receiving_account": "Konto odbiorcze", + "section_label": "Hash bloku", + "sending_account": "Konto nadawcze", + "seo_description": "Informacje związane z blokiem Nano", + "seo_title": "Blok Nano", + "voting_weight": "Waga głosowania" + }, + "block_info": { + "block_account": "Konto bloku", + "operation": "Operacja", + "status": "Status", + "timestamp": "Znacznik czasu" + }, + "block_status": { + "confirmed": "Potwierdzony", + "unconfirmed": "Niepotwierdzony" + }, + "block_type": { + "change": "Zmiana", + "epoch": "Epoka", + "open": "Otwarcie", + "receive": "Odbiór", + "send": "Wysyłka" + }, + "common": { + "account_one": "Konto", + "account_other": "Konta", + "address": "Adres", + "balance": "Saldo", + "bandwidth_limit": "Limit przepustowości", + "bandwidth_limit_short": "Limit BW", + "blocks": "Bloki", + "blocks_behind": "Bloki zaległe", + "blocks_diff_short": "Różnica bloków", + "by_online_weight": "Według wagi online", + "clear_filters": "Wyczyść filtry", + "click_to_copy": "Kliknij, aby skopiować", + "collapse": "Zwiń", + "conf_short": "Potw.", + "conf_diff_short": "Różn. Potw.", + "confirmations_behind": "Potwierdzeń w tyle", + "country": "Kraj", + "delegator_one": "Delegujący", + "delegator_other": "Delegujący", + "max": "Maks", + "min": "Min", + "offline": "Offline", + "online": "Online", + "peers": "Rówieśnicy", + "percent_of_total": "% całości", + "port": "Port", + "quorum_delta": "Delta kworum", + "representative_one": "Przedstawiciel", + "representative_other": "Przedstawiciele", + "show_more": "Pokaż więcej {{count}}", + "total": "Całkowity", + "unchecked": "Niezweryfikowane", + "unchecked_count": "Liczba niezweryfikowanych", + "unlimited": "Nieograniczony", + "uptime": "Czas działania", + "version": "Wersja", + "weight": "Waga" + }, + "delegators": { + "showing_top_delegators": "Pokazuje 100 najlepszych delegujących z minimalnym saldem 1 Nano." + }, + "doc": { + "contributors": "Współtwórca", + "document_not_found": "Dokument (lub konto) nie znaleziony", + "edit_page": "Edytuj stronę", + "help_out": "Pomóż", + "not_found_404": "404", + "section_link_copied": "Link do sekcji skopiowany", + "updated_by": "zaktualizowane przez" + }, + "github_events": { + "action": { + "added_member": "dodano członka", + "commented_on_commit": "skomentowano commit", + "commented_on_issue": "skomentowano problem", + "commented_on_pr_review": "skomentowano recenzję pr", + "created": "utworzono {{action}}", + "deleted": "usunięto {{action}}", + "forked": "zforkowano", + "issue_action": "{{action}} problem", + "made_public": "udostępniono publicznie", + "pr_action": "{{action}} pr", + "pr_review": "recenzja pr {{title}}", + "published_release": "opublikowano wydanie", + "pushed_commit": "wysłano commit do {{ref}}", + "sponsorship_started": "rozpoczęto sponsoring", + "watching_repo": "obserwowanie repo" + }, + "events_title": "Wydarzenia rozwojowe" + }, + "ledger": { + "addresses": { + "active_detail": "Aktywne pokazuje liczbę unikalnych adresów użytych. Nowe pokazuje liczbę utworzonych adresów. Ponownie użyte pokazuje liczbę adresów użytych, które zostały utworzone w poprzednim dniu.", + "active_stats": "Statystyki aktywnych adresów", + "new_stats": "Statystyki nowych adresów", + "total_number": "Całkowita liczba aktywnych, nowych i ponownie użytych adresów użytych każdego dnia." + }, + "amounts": { + "total_number": "Liczba potwierdzonych bloków typu wysyłka na dzień, gdzie kwota w bloku mieści się w danym zakresie (w Nano)" + }, + "blocks": { + "change": "Statystyki bloków zmian", + "description": "Liczba bloków potwierdzonych każdego dnia.", + "open": "Statystyki bloków otwarcia", + "receive": "Statystyki bloków odbioru", + "send": "Statystyki bloków wysyłki", + "total": "Statystyki całkowitych bloków" + }, + "description": "Opis", + "usd_transferred": { + "desc_1": "Całkowita wartość przesłana (w USD) na dzień.", + "desc_2": "Na podstawie dziennej ceny zamknięcia Nano/USD i całkowitej ilości Nano przesłanej tego dnia.", + "usd_transferred": "Przesłane USD", + "usd_transferred_stats": "Statystyki przesłanych USD" + }, + "volume": { + "change_stats": "Statystyki zmian", + "description": "Całkowita wysłana kwota (w Nano) i całkowita zmiana wagi głosowania na dzień.", + "send_stats": "Statystyki wysyłki" + } + }, + "ledger_page": { + "addresses_tab": "Adresy", + "amounts_tab": "Kwoty", + "blocks_tab": "Bloki", + "seo_description": "Metryki i analizy łańcucha Nano", + "seo_title": "Analiza łańcucha Nano", + "value_transferred_tab": "Przesłana wartość", + "volume_tab": "Wolumen" + }, + "menu": { + "account_setup": "Konfiguracja konta", + "acquiring": "Nabycie", + "advantages": "Zalety", + "attack_vectors": "Weektory ataku", + "basics": "Podstawy", + "best_practices": "Najlepsze praktyki", + "choosing_a_rep": "Wybór reprezentanta", + "challenges": "Wyzwania", + "communities": "Społeczności", + "contribution_guide": "Przewodnik po wkładach", + "design": "Projekt", + "developer_discussions": "Dyskusje deweloperów", + "developers": "Deweloperzy", + "documentation": "Dokumentacja", + "faqs": "FAQ", + "get_involved": "Zaangażuj się", + "get_support": "Uzyskaj wsparcie", + "getting_started": "Rozpoczynanie", + "glossary": "Słownik", + "guides": "Przewodniki", + "history": "Historia", + "home": "Strona główna", + "how_it_works": "Jak to działa", + "integrations": "Integracje", + "introduction": "Wprowadzenie", + "investment_thesis": "Teza inwestycyjna", + "learn": "Ucz się", + "ledger": "Księga", + "misconceptions": "Nieporozumienia", + "overview": "Przegląd", + "planning": "Planowanie", + "privacy": "Prywatność", + "protocol": "Protokół", + "running_a_node": "Uruchamianie węzła", + "security": "Bezpieczeństwo", + "stats": "Statystyki", + "storing": "Przechowywanie", + "telemetry": "Telemetria", + "topics": "Tematy", + "using": "Używanie", + "why_it_matters": "Dlaczego ma to znaczenie" + }, + "network": { + "backlog_text": "Średnia liczba transakcji oczekujących na potwierdzenie $(network.pr_text)", + "censor_text": "Minimalna liczba reprezentantów potrzebnych do cenzurowania transakcji lub zatrzymania sieci", + "confirm_text": "Minimalna liczba reprezentantów potrzebnych do potwierdzenia transakcji", + "confirmations": "Potwierdzenia (24h)", + "confirmations_text": "Całkowita liczba transakcji potwierdzonych przez sieć w ciągu ostatnich 24 godzin", + "energy_text": "Szacowane zużycie energii CPU przez głównych reprezentantów na żywo w sieci na podstawie zebranych informacji o modelu CPU. Szacunek opiera się na TDP CPU, czyli średniej mocy, w watach, którą procesor rozprasza podczas pracy z podstawową częstotliwością z wszystkimi aktywnymi rdzeniami pod obciążeniem o wysokiej złożoności zdefiniowanym przez producenta", + "energy_usage": "Zużycie energii (TDP) (24h)", + "fee_text": "Sieć Nano działa bez opłat", + "nano_ticker": "NanoTicker", + "online_stake": "Stawka online", + "principal_reps": "Główni Reprezentanci", + "pr_text": "jak zaobserwowano w sieci głównych reprezentantów: węzłów głosujących z więcej niż 0,1% delegowanej wagi głosowania online", + "reps_to_censor": "Reprezentanci do cenzury lub zatrzymania", + "reps_to_confirm": "Reprezentanci do potwierdzenia", + "settlement": "Rozliczenie (24h)", + "settlement_text": "Całkowita wartość rozliczona przez sieć w ciągu ostatnich 24 godzin", + "speed_text": "Czas w milisekundach potrzebny na potwierdzenie testowej transakcji", + "stake_text": "Procent delegowanej wagi Nano aktywnie uczestniczącej w głosowaniu", + "stats_title": "Statystyki sieci", + "total_reps": "Łączni Reprezentanci (24h)", + "tx_backlog": "Zaległości transakcji", + "tx_fees": "Opłaty transakcyjne (24h)", + "tx_speed": "Prędkość transakcji", + "tx_throughput": "Przepustowość transakcji", + "throughput_text": "Średnia liczba transakcji potwierdzonych na sekundę w ostatniej minucie $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Fundacja Nano", + "top": "Top", + "trending": "Trendy" + }, + "representative_alerts": { + "table_header": { + "behind": "Zaległości", + "issue": "Problem", + "last_online": "Ostatnio online", + "percent_online_weight": "% Wagi online", + "representative": "Reprezentant" + }, + "tooltip": { + "behind": "Reprezentant ma zaległości lub jest w trakcie bootstrappingu. Granica to liczba zacementowanych poza 95. percentylem. (poprzez telemetrię)", + "low_uptime": "Reprezentant był offline więcej niż 25% w ciągu ostatnich 28 dni.", + "offline": "Reprezentant przestał głosować i wydaje się być offline.", + "overweight": "Reprezentant ma więcej niż 3M wagi głosowania Nano. Delegaci powinni rozważyć dystrybucję wagi, aby poprawić odporność sieci i wartość." + }, + "type": { + "behind": "Zaległości", + "low_uptime": "Niska dostępność", + "offline": "Offline", + "overweight": "Nadwaga" + } + }, + "representatives_cemented_by_weight": { + "title": "Różnica potwierdzeń", + "tooltip": "Wyświetla ilość wagi głosowania, która znajduje się w X liczbie potwierdzeń od wiodącego węzła. Pomocne w wiedzy, jak dobrze węzły są zsynchronizowane i wyrównane w całej sieci" + }, + "representatives_checked_by_weight": { + "title": "Różnica bloków", + "tooltip": "Wyświetla ilość wagi głosowania, która znajduje się w X liczbie bloków od wiodącego węzła. Przydatne do uzyskania poczucia, jak dobrze propagacja bloków jest zsynchronizowana w sieci" + }, + "representative_delegators": { + "showing_top_delegators": "Pokazuje 100 najlepszych delegatów z minimalnym saldem 1 Nano." + }, + "representative_info": { + "first_seen": "Pierwszy raz widziany", + "last_seen": "Ostatnio widziany", + "weight_represented": "Waga reprezentowana" + }, + "representative_network": { + "city": "Miasto", + "isp": "Dostawca Internetu", + "network": "Sieć", + "provider": "Dostawca" + }, + "representative_telemetry": { + "telemetry": "Telemetria", + "telemetry_timestamp": "Znacznik czasu telemetrii" + }, + "representative_uptime": { + "2m_uptime": "Czas pracy 2M", + "2w_uptime": "Czas pracy 2W", + "3m_uptime": "Czas pracy 3M", + "current_status": "Aktualny status", + "down": "Nieaktywny", + "down_for": "Nieaktywny przez", + "operational": "Operacyjny", + "up_for": "Aktywny przez", + "warning": "Ostrzeżenie" + }, + "representatives": { + "alias": "Alias", + "cpu_cores": "Rdzenie CPU", + "cpu_model": "Model CPU", + "tdp": "TDP (wH)", + "protocol_version": "Protokół", + "last_seen": "Ostatnio widziany", + "host_asn": "ASN hosta" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Wyświetla ilość wagi głosowania na podstawie limitu przepustowości ustawionego lokalnie przez każdy węzeł" + }, + "representatives_country_by_weight": { + "title": "Kraj" + }, + "representatives_offline": { + "account": "Konto offline", + "last_online": "Ostatnio online" + }, + "representatives_page": { + "seo_description": "Eksploruj i analizuj reprezentantów sieci Nano", + "seo_title": "Eksplorator Reprezentantów Nano", + "telemetry_tab": "Telemetria", + "weight_distribution_tab": "Dystrybucja wagi", + "weight_history_tab": "Historia wagi", + "offline_reps_tab": "Reprezentanci offline" + }, + "representatives_provider_by_weight": { + "title": "Dostawca hostingu" + }, + "representatives_quorum_charts": { + "peers_weight": "Waga rówieśników", + "quorum_delta": "Delta kworum", + "title": "Wykresy kworum", + "trended_weight": "Waga trendu" + }, + "representatives_search": { + "placeholder": "Filtruj po koncie, aliasie, ip" + }, + "representatives_weight": { + "trended": "Trendowana" + }, + "representatives_weight_chart": { + "title": "Dystrybucja wagi według reprezentanta" + }, + "representatives_version_by_weight": { + "title": "Wersje" + }, + "roadmap": { + "header": { + "subtitle": "Cele społeczności", + "title": "Planowanie" + }, + "seo": { + "description": "Droga rozwoju i mapa społeczności Nano", + "tags": [ + "mapa drogowa", + "nano", + "przyszłość", + "wydanie", + "projekt", + "zadania", + "dyskusje", + "społeczność", + "ambasadorzy", + "menedżerowie" + ], + "title": "Mapa drogowa" + } + }, + "search_bar": { + "placeholder": "Szukaj po adresie / Hashu bloku" + }, + "uptime": { + "now": "Teraz", + "days_ago": "dni temu" + } +} diff --git a/locales/pt.json b/locales/pt.json new file mode 100644 index 00000000..23468bd1 --- /dev/null +++ b/locales/pt.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Endereço da Conta", + "change_summary": "Resumo da Mudança", + "copy_notification": "Endereço da conta copiado", + "seo_description": "Informações para representante nano", + "seo_title": "Conta Nano", + "telemetry_charts": "Gráficos de Telemetria", + "unopened_description": "Embora o endereço da conta seja válido, nenhum bloco foi observado. Se NANO foi enviado para esta conta, ainda é necessário publicar um bloco correspondente para receber os fundos e estabelecer um saldo inicial. O saldo de uma conta só pode ser atualizado pelo titular da conta, pois são os únicos que podem publicar blocos em sua cadeia.", + "unopened_note": "Se um bloco de abertura já foi publicado, pode levar alguns momentos para se espalhar pela rede e ser observado pelos nós da nano.community.", + "unopened_title": "Esta conta ainda não foi aberta" + }, + "account_blocks_summary": { + "first_timestamp": "Primeiro Registro de Tempo", + "last_timestamp": "Último Registro de Tempo", + "max_amount": "Quantidade Máxima", + "min_amount": "Quantidade Mínima", + "no_records": "Sem Registros", + "receiving_account": "Conta Receptora", + "representative_account": "Conta Representativa", + "sending_account": "Conta Remetente", + "showing_top_10": "Mostrando as 10 principais contas por total decrescente", + "transactions": "TXs" + }, + "account_meta": { + "account_info": "Informações da Conta", + "funding_account": "Conta de Financiamento", + "funding_timestamp": "Registro de Tempo do Financiamento", + "height": "Altura", + "last_modified": "Última Modificação", + "open_timestamp": "Registro de Tempo de Abertura", + "opening_balance": "Saldo de Abertura", + "receivable_balance": "Saldo a Receber" + }, + "block_page": { + "amount": "Quantidade", + "copy_notification": "Hash do bloco copiado", + "delegated_representative": "Representante Delegado", + "description": "Descrição", + "epoch_v1": "Época v1 — Cadeias de contas atualizadas de blocos legados (abrir, receber, enviar, mudar) para blocos de estado.", + "epoch_v2": "Época v2 - Cadeias de contas atualizadas para usar dificuldade de Prova de Trabalho mais alta.", + "receiving_account": "Conta Receptora", + "section_label": "Hash do Bloco", + "sending_account": "Conta Remetente", + "seo_description": "Informações relacionadas a um Bloco Nano", + "seo_title": "Bloco Nano", + "voting_weight": "Peso de Votação" + }, + "block_info": { + "block_account": "Conta do Bloco", + "operation": "Operação", + "status": "Status", + "timestamp": "Registro de Tempo" + }, + "block_status": { + "confirmed": "Confirmado", + "unconfirmed": "Não Confirmado" + }, + "block_type": { + "change": "Mudança", + "epoch": "Época", + "open": "Abrir", + "receive": "Receber", + "send": "Enviar" + }, + "common": { + "account_one": "Conta", + "account_other": "Contas", + "address": "Endereço", + "balance": "Saldo", + "bandwidth_limit": "Limite de Largura de Banda", + "bandwidth_limit_short": "Limite de LB", + "blocks": "Blocos", + "blocks_behind": "Blocos Atrás", + "blocks_diff_short": "Dif. de Blocos", + "by_online_weight": "Por Peso Online", + "clear_filters": "Limpar Filtros", + "click_to_copy": "Clique para copiar", + "collapse": "Colapso", + "conf_short": "Conf.", + "conf_diff_short": "Dif. Conf", + "confirmations_behind": "Confirmações Atrás", + "country": "País", + "delegator_one": "Delegador", + "delegator_other": "Delegadores", + "max": "Máx", + "min": "Mín", + "offline": "Offline", + "online": "Online", + "peers": "Pares", + "percent_of_total": "% do Total", + "port": "Porta", + "quorum_delta": "Delta do Quórum", + "representative_one": "Representante", + "representative_other": "Representantes", + "show_more": "Mostrar mais {{count}}", + "total": "Total", + "unchecked": "Não Verificado", + "unchecked_count": "Contagem Não Verificada", + "unlimited": "Ilimitado", + "uptime": "Tempo de Atividade", + "version": "Versão", + "weight": "Peso" + }, + "delegators": { + "showing_top_delegators": "Mostrando os 100 principais delegadores com um saldo mínimo de 1 Nano." + }, + "doc": { + "contributors": "Contribuidor", + "document_not_found": "Documento (ou Conta) não encontrado", + "edit_page": "Editar Página", + "help_out": "Ajude", + "not_found_404": "404", + "section_link_copied": "Link da seção copiado", + "updated_by": "atualizado por" + }, + "github_events": { + "action": { + "added_member": "membro adicionado", + "commented_on_commit": "comentou no commit", + "commented_on_issue": "comentou no problema", + "commented_on_pr_review": "comentou na revisão de pr", + "created": "criado {{action}}", + "deleted": "deletado {{action}}", + "forked": "bifurcado", + "issue_action": "{{action}} problema", + "made_public": "tornou público", + "pr_action": "{{action}} pr", + "pr_review": "revisão de pr {{title}}", + "published_release": "lançamento publicado", + "pushed_commit": "commit enviado para {{ref}}", + "sponsorship_started": "patrocínio iniciado", + "watching_repo": "observando repositório" + }, + "events_title": "Eventos de Desenvolvimento" + }, + "ledger": { + "addresses": { + "active_detail": "Ativo mostra o número de endereços únicos usados. Novo mostra o número de endereços criados. Reutilizado mostra o número de endereços usados que foram criados em um dia anterior.", + "active_stats": "Estatísticas de Endereço Ativo", + "new_stats": "Estatísticas de Novo Endereço", + "total_number": "O número total de endereços ativos, novos e reutilizados usados por dia." + }, + "amounts": { + "total_number": "O número de blocos do tipo envio confirmados por dia onde a quantidade no bloco está em uma determinada faixa (em Nano)" + }, + "blocks": { + "change": "Estatísticas de Bloco de Mudança", + "description": "O número de blocos confirmados por dia.", + "open": "Estatísticas de Bloco de Abertura", + "receive": "Estatísticas de Bloco de Recebimento", + "send": "Estatísticas de Bloco de Envio", + "total": "Estatísticas de Bloco Total" + }, + "description": "Descrição", + "usd_transferred": { + "desc_1": "O valor total transferido (em USD) por dia.", + "desc_2": "Baseado no preço de fechamento diário de Nano/USD e no total de Nano transferido naquele dia.", + "usd_transferred": "USD Transferido", + "usd_transferred_stats": "Estatísticas de USD Transferido" + }, + "volume": { + "change_stats": "Estatísticas de Mudança", + "description": "O valor total enviado (em Nano) e o total de peso de votação alterado por dia.", + "send_stats": "Estatísticas de Envio" + } + }, + "ledger_page": { + "addresses_tab": "Endereços", + "amounts_tab": "Quantidades", + "blocks_tab": "Blocos", + "seo_description": "Métricas e análises on-chain do livro-razão Nano", + "seo_title": "Análise do Livro-Razão Nano", + "value_transferred_tab": "Valor Transferido", + "volume_tab": "Volume" + }, + "menu": { + "account_setup": "Configuração da Conta", + "acquiring": "Adquirindo", + "advantages": "Vantagens", + "attack_vectors": "Vetores de Ataque", + "basics": "Básicos", + "best_practices": "Melhores Práticas", + "choosing_a_rep": "Escolhendo um Rep", + "challenges": "Desafios", + "communities": "Comunidades", + "contribution_guide": "Guia de Contribuição", + "design": "Design", + "developer_discussions": "Discussões de Desenvolvedores", + "developers": "Desenvolvedores", + "documentation": "Documentação", + "faqs": "FAQs", + "get_involved": "Envolver-se", + "get_support": "Obter Suporte", + "getting_started": "Começando", + "glossary": "Glossário", + "guides": "Guias", + "history": "História", + "home": "Início", + "how_it_works": "Como Funciona", + "integrations": "Integrações", + "introduction": "Introdução", + "investment_thesis": "Tese de Investimento", + "learn": "Aprender", + "ledger": "Livro-Razão", + "misconceptions": "Equívocos", + "overview": "Visão Geral", + "planning": "Planejamento 👾", + "privacy": "Privacidade", + "protocol": "Protocolo", + "running_a_node": "Executando um Nó", + "security": "Segurança", + "stats": "Estatísticas", + "storing": "Armazenando", + "telemetry": "Telemetria", + "topics": "Tópicos", + "using": "Usando", + "why_it_matters": "Por Que Isso Importa" + }, + "network": { + "backlog_text": "Número médio de transações esperando para serem confirmadas $(network.pr_text)", + "censor_text": "O número mínimo de representantes necessários para censurar transações ou paralisar a rede", + "confirm_text": "O número mínimo de representantes necessários para confirmar transações", + "confirmations": "Confirmações (24h)", + "confirmations_text": "Número total de transações confirmadas pela rede nas últimas 24 horas", + "energy_text": "Estimativa de uso de energia da CPU da rede ao vivo de Representantes Principais baseada em informações coletadas do modelo de CPU. A estimativa é baseada no TDP da CPU, que é a potência média, em watts, que o processador dissipa quando opera na frequência base com todos os núcleos ativos sob uma carga de trabalho de alta complexidade definida pelo fabricante", + "energy_usage": "Uso de Energia (TDP) (24h)", + "fee_text": "A rede Nano opera sem taxas", + "nano_ticker": "NanoTicker", + "online_stake": "Participação Online", + "principal_reps": "Representantes Principais", + "pr_text": "conforme observado nos representantes principais da rede: nós de votação com mais de 0,1% do peso de votação online delegado a eles", + "reps_to_censor": "Representantes para Censurar ou Paralisar", + "reps_to_confirm": "Representantes para Confirmar", + "settlement": "Liquidação (24h)", + "settlement_text": "Quantidade total de valor liquidado pela rede nas últimas 24 horas", + "speed_text": "Tempo em milissegundos para uma transação de teste ser confirmada", + "stake_text": "Porcentagem do peso Nano delegado participando ativamente na votação", + "stats_title": "Estatísticas da Rede", + "total_reps": "Total de Representantes (24h)", + "tx_backlog": "Backlog de Tx", + "tx_fees": "Taxas de Tx (24h)", + "tx_speed": "Velocidade de Tx", + "tx_throughput": "Throughput de Tx", + "throughput_text": "Número médio de transações confirmadas por segundo no último minuto $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Fundação Nano", + "top": "Topo", + "trending": "Tendências" + }, + "representative_alerts": { + "table_header": { + "behind": "Atrasado", + "issue": "Problema", + "last_online": "Última vez online", + "percent_online_weight": "% Peso Online", + "representative": "Representante" + }, + "tooltip": { + "behind": "Representante está atrasado ou em processo de inicialização. O limite é uma contagem cimentada além do percentil 95. (via telemetria)", + "low_uptime": "Representante esteve offline mais de 25% nos últimos 28 dias.", + "offline": "Representante parou de votar e parece estar offline.", + "overweight": "Representante tem mais de 3M de peso de voto Nano. Delegadores devem considerar distribuir o peso para melhorar a resiliência e o valor da rede." + }, + "type": { + "behind": "Atrasado", + "low_uptime": "Baixa Disponibilidade", + "offline": "Offline", + "overweight": "Sobrepeso" + } + }, + "representatives_cemented_by_weight": { + "title": "Diferencial de Confirmação", + "tooltip": "Mostra a quantidade de peso de voto que está dentro de X número de confirmações do nó líder. Útil para saber quão bem sincronizados e alinhados estão os nós em toda a rede" + }, + "representatives_checked_by_weight": { + "title": "Diferencial de Blocos", + "tooltip": "Mostra a quantidade de peso de voto que está dentro de X número de blocos do nó líder. Útil para ter uma ideia de quão bem a propagação de blocos está sincronizada dentro da rede" + }, + "representative_delegators": { + "showing_top_delegators": "Mostrando os 100 principais delegadores com um saldo mínimo de 1 Nano." + }, + "representative_info": { + "first_seen": "Visto pela Primeira Vez", + "last_seen": "Visto pela Última Vez", + "weight_represented": "Peso Representado" + }, + "representative_network": { + "city": "Cidade", + "isp": "ISP", + "network": "Rede", + "provider": "Provedor" + }, + "representative_telemetry": { + "telemetry": "Telemetria", + "telemetry_timestamp": "Timestamp da Telemetria" + }, + "representative_uptime": { + "2m_uptime": "Disponibilidade de 2M", + "2w_uptime": "Disponibilidade de 2S", + "3m_uptime": "Disponibilidade de 3M", + "current_status": "Status Atual", + "down": "Desligado", + "down_for": "Desligado por", + "operational": "Operacional", + "up_for": "Ligado por", + "warning": "Aviso" + }, + "representatives": { + "alias": "Apelido", + "cpu_cores": "Núcleos da CPU", + "cpu_model": "Modelo da CPU", + "tdp": "TDP (wH)", + "protocol_version": "Protocolo", + "last_seen": "Visto pela Última Vez", + "host_asn": "ASN do Host" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Mostra a quantidade de peso de voto baseada no limite de largura de banda definido localmente por cada nó" + }, + "representatives_country_by_weight": { + "title": "País" + }, + "representatives_offline": { + "account": "Conta Offline", + "last_online": "Última vez Online" + }, + "representatives_page": { + "seo_description": "Explore e analise os representantes da rede Nano", + "seo_title": "Explorador de Representantes Nano", + "telemetry_tab": "Telemetria", + "weight_distribution_tab": "Distribuição de Peso", + "weight_history_tab": "Histórico de Peso", + "offline_reps_tab": "Representantes Offline" + }, + "representatives_provider_by_weight": { + "title": "Provedor de Hospedagem" + }, + "representatives_quorum_charts": { + "peers_weight": "Peso dos Pares", + "quorum_delta": "Delta do Quórum", + "title": "Gráficos de Quórum", + "trended_weight": "Peso Tendenciado" + }, + "representatives_search": { + "placeholder": "Filtrar por conta, apelido, ip" + }, + "representatives_weight": { + "trended": "Tendenciado" + }, + "representatives_weight_chart": { + "title": "Distribuição de Peso por Representante" + }, + "representatives_version_by_weight": { + "title": "Versões" + }, + "roadmap": { + "header": { + "subtitle": "Objetivos da Comunidade", + "title": "Planejamento" + }, + "seo": { + "description": "Roteiro de desenvolvimento e comunidade Nano", + "tags": [ + "roteiro", + "nano", + "futuro", + "lançamento", + "design", + "tarefas", + "discussões", + "comunidade", + "embaixadores", + "gerentes" + ], + "title": "Roteiro" + } + }, + "search_bar": { + "placeholder": "Pesquisar por Endereço / Hash do Bloco" + }, + "uptime": { + "now": "Agora", + "days_ago": "dias atrás" + } +} diff --git a/locales/ru.json b/locales/ru.json new file mode 100644 index 00000000..09a1889f --- /dev/null +++ b/locales/ru.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Адрес аккаунта", + "change_summary": "Изменить сводку", + "copy_notification": "Адрес аккаунта скопирован", + "seo_description": "Информация для представителя нано", + "seo_title": "Аккаунт Nano", + "telemetry_charts": "Телеметрические графики", + "unopened_description": "Хотя адрес аккаунта действителен, блоки не наблюдались. Если NANO были отправлены на этот аккаунт, необходимо опубликовать соответствующий блок для получения средств и установления начального баланса. Баланс аккаунта может быть обновлен только владельцем аккаунта, так как только они могут публиковать блоки в своей цепочке.", + "unopened_note": "Если открывающий блок уже был опубликован, может потребоваться несколько моментов, чтобы он распространился по сети и был замечен узлами nano.community.", + "unopened_title": "Этот аккаунт еще не был открыт" + }, + "account_blocks_summary": { + "first_timestamp": "Первая отметка времени", + "last_timestamp": "Последняя отметка времени", + "max_amount": "Максимальная сумма", + "min_amount": "Минимальная сумма", + "no_records": "Записей нет", + "receiving_account": "Получающий аккаунт", + "representative_account": "Представительский аккаунт", + "sending_account": "Отправляющий аккаунт", + "showing_top_10": "Показаны 10 лучших аккаунтов по убыванию общей суммы", + "transactions": "Транзакции" + }, + "account_meta": { + "account_info": "Информация об аккаунте", + "funding_account": "Финансирующий аккаунт", + "funding_timestamp": "Время финансирования", + "height": "Высота", + "last_modified": "Последнее изменение", + "open_timestamp": "Время открытия", + "opening_balance": "Начальный баланс", + "receivable_balance": "Получаемый баланс" + }, + "block_page": { + "amount": "Сумма", + "copy_notification": "Хэш блока скопирован", + "delegated_representative": "Делегированный представитель", + "description": "Описание", + "epoch_v1": "Эпоха v1 — Обновление цепочек аккаунтов с устаревших блоков (открытие, получение, отправка, изменение) до состояний блоков.", + "epoch_v2": "Эпоха v2 - Обновление цепочек аккаунтов для использования более высокой сложности Proof-of-Work.", + "receiving_account": "Получающий аккаунт", + "section_label": "Хэш блока", + "sending_account": "Отправляющий аккаунт", + "seo_description": "Информация, связанная с блоком Nano", + "seo_title": "Блок Nano", + "voting_weight": "Вес голоса" + }, + "block_info": { + "block_account": "Аккаунт блока", + "operation": "Операция", + "status": "Статус", + "timestamp": "Отметка времени" + }, + "block_status": { + "confirmed": "Подтверждено", + "unconfirmed": "Не подтверждено" + }, + "block_type": { + "change": "Изменение", + "epoch": "Эпоха", + "open": "Открыть", + "receive": "Получить", + "send": "Отправить" + }, + "common": { + "account_one": "Аккаунт", + "account_other": "Аккаунты", + "address": "Адрес", + "balance": "Баланс", + "bandwidth_limit": "Лимит пропускной способности", + "bandwidth_limit_short": "Лимит ПС", + "blocks": "Блоки", + "blocks_behind": "Блоков позади", + "blocks_diff_short": "Разн. блоков", + "by_online_weight": "По онлайн весу", + "clear_filters": "Очистить фильтры", + "click_to_copy": "Нажмите, чтобы скопировать", + "collapse": "Свернуть", + "conf_short": "Подтв.", + "conf_diff_short": "Разн. подтв.", + "confirmations_behind": "Подтверждений позади", + "country": "Страна", + "delegator_one": "Делегатор", + "delegator_other": "Делегаторы", + "max": "Макс", + "min": "Мин", + "offline": "Оффлайн", + "online": "Онлайн", + "peers": "Пиры", + "percent_of_total": "% от общего", + "port": "Порт", + "quorum_delta": "Дельта кворума", + "representative_one": "Представитель", + "representative_other": "Представители", + "show_more": "Показать еще {{count}}", + "total": "Всего", + "unchecked": "Не проверено", + "unchecked_count": "Количество не проверенных", + "unlimited": "Неограниченно", + "uptime": "Время работы", + "version": "Версия", + "weight": "Вес" + }, + "delegators": { + "showing_top_delegators": "Показаны 100 лучших делегаторов с минимальным балансом в 1 Nano." + }, + "doc": { + "contributors": "Участник", + "document_not_found": "Документ (или аккаунт) не найден", + "edit_page": "Редактировать страницу", + "help_out": "Помочь", + "not_found_404": "404", + "section_link_copied": "Ссылка на раздел скопирована", + "updated_by": "обновлено" + }, + "github_events": { + "action": { + "added_member": "добавлен участник", + "commented_on_commit": "прокомментирован коммит", + "commented_on_issue": "прокомментирована проблема", + "commented_on_pr_review": "прокомментирован обзор пулл-реквеста", + "created": "создано {{action}}", + "deleted": "удалено {{action}}", + "forked": "форкнуто", + "issue_action": "{{action}} проблема", + "made_public": "сделано публичным", + "pr_action": "{{action}} пулл-реквест", + "pr_review": "обзор пулл-реквеста {{title}}", + "published_release": "опубликован релиз", + "pushed_commit": "отправлен коммит в {{ref}}", + "sponsorship_started": "начат спонсорство", + "watching_repo": "просмотр репозитория" + }, + "events_title": "События разработки" + }, + "ledger": { + "addresses": { + "active_detail": "Активные показывает количество уникальных использованных адресов. Новые показывает количество созданных адресов. Повторно используемые показывает количество использованных адресов, созданных в предыдущие дни.", + "active_stats": "Статистика активных адресов", + "new_stats": "Статистика новых адресов", + "total_number": "Общее количество активных, новых и повторно используемых адресов, используемых в день." + }, + "amounts": { + "total_number": "Количество подтвержденных блоков отправки в день, где сумма в блоке находится в заданном диапазоне (в Nano)" + }, + "blocks": { + "change": "Статистика блоков изменения", + "description": "Количество подтвержденных блоков в день.", + "open": "Статистика открытых блоков", + "receive": "Статистика блоков получения", + "send": "Статистика блоков отправки", + "total": "Общая статистика блоков" + }, + "description": "Описание", + "usd_transferred": { + "desc_1": "Общая сумма переданной стоимости (в USD) в день.", + "desc_2": "Основано на закрытии дневной цены Nano/USD и общей сумме переданного Nano в тот день.", + "usd_transferred": "Передано в USD", + "usd_transferred_stats": "Статистика передачи в USD" + }, + "volume": { + "change_stats": "Статистика изменений", + "description": "Общая отправленная сумма (в Nano) и общая сумма измененного веса голосования в день.", + "send_stats": "Статистика отправок" + } + }, + "ledger_page": { + "addresses_tab": "Адреса", + "amounts_tab": "Суммы", + "blocks_tab": "Блоки", + "seo_description": "Метрики и аналитика блокчейна Nano", + "seo_title": "Анализ блокчейна Nano", + "value_transferred_tab": "Переданная стоимость", + "volume_tab": "Объем" + }, + "menu": { + "account_setup": "Настройка аккаунта", + "acquiring": "Приобретение", + "advantages": "Преимущества", + "attack_vectors": "Векторы атак", + "basics": "Основы", + "best_practices": "Лучшие практики", + "choosing_a_rep": "Выбор представителя", + "challenges": "Вызовы", + "communities": "Сообщества", + "contribution_guide": "Руководство по вкладу", + "design": "Дизайн", + "developer_discussions": "Обсуждения разработчиков", + "developers": "Разработчики", + "documentation": "Документация", + "faqs": "ЧаВо", + "get_involved": "Принять участие", + "get_support": "Получить поддержку", + "getting_started": "Начало работы", + "glossary": "Глоссарий", + "guides": "Руководства", + "history": "История", + "home": "Главная", + "how_it_works": "Как это работает", + "integrations": "Интеграции", + "introduction": "Введение", + "investment_thesis": "Инвестиционная теза", + "learn": "Учиться", + "ledger": "Блокчейн", + "misconceptions": "Заблуждения", + "overview": "Обзор", + "planning": "Планирование 👾", + "privacy": "Конфиденциальность", + "protocol": "Протокол", + "running_a_node": "Управление узлом", + "security": "Безопасность", + "stats": "Статистика", + "storing": "Хранение", + "telemetry": "Телеметрия", + "topics": "Темы", + "using": "Использование", + "why_it_matters": "Почему это важно" + }, + "network": { + "backlog_text": "Медианное количество транзакций, ожидающих подтверждения $(network.pr_text)", + "censor_text": "Минимальное количество представителей, необходимых для цензурирования транзакций или остановки сети", + "confirm_text": "Минимальное количество представителей, необходимых для подтверждения транзакций", + "confirmations": "Подтверждения (24ч)", + "confirmations_text": "Общее количество транзакций, подтвержденных сетью за последние 24 часа", + "energy_text": "Оценка потребления энергии ЦПУ живой сети основных представителей на основе собранной информации о модели ЦПУ. Оценка основана на TDP ЦПУ, которая является средней мощностью в ваттах, рассеиваемой процессором при работе на базовой частоте со всеми активными ядрами под нагрузкой высокой сложности, определенной производителем", + "energy_usage": "Использование энергии (TDP) (24ч)", + "fee_text": "Сеть Nano работает без комиссий", + "nano_ticker": "Тикер Nano", + "online_stake": "Онлайн ставка", + "principal_reps": "Основные представители", + "pr_text": "как наблюдается по всей сети основных представителей: голосующих узлов с более чем 0.1% онлайн веса голосования, делегированных им", + "reps_to_censor": "Представители для цензуры или остановки", + "reps_to_confirm": "Представители для подтверждения", + "settlement": "Расчет (24ч)", + "settlement_text": "Общая сумма стоимости, урегулированной сетью за последние 24 часа", + "speed_text": "Время в миллисекундах для подтверждения тестовой транзакции", + "stake_text": "Процент делегированного веса Nano, активно участвующего в голосовании", + "stats_title": "Статистика сети", + "total_reps": "Всего представителей (24ч)", + "tx_backlog": "Очередь транзакций", + "tx_fees": "Комиссии за транзакции (24ч)", + "tx_speed": "Скорость транзакций", + "tx_throughput": "Пропускная способность транзакций", + "throughput_text": "Медианное количество транзакций, подтвержденных в секунду за последнюю минуту $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Фонд Nano", + "top": "Топ", + "trending": "Тренды" + }, + "representative_alerts": { + "table_header": { + "behind": "Позади", + "issue": "Проблема", + "last_online": "Последний раз онлайн", + "percent_online_weight": "% Онлайн веса", + "representative": "Представитель" + }, + "tooltip": { + "behind": "Представитель отстал или загружается. Критерий - цементированный счет за пределами 95-го процентиля. (через телеметрию)", + "low_uptime": "Представитель был оффлайн более 25% в последние 28 дней.", + "offline": "Представитель прекратил голосование и кажется оффлайн.", + "overweight": "У представителя более 3M Nano веса голосования. Делегаторам следует рассмотреть возможность распределения веса для улучшения устойчивости сети и ее ценности." + }, + "type": { + "behind": "Отстает", + "low_uptime": "Низкое время работы", + "offline": "Оффлайн", + "overweight": "Избыточный вес" + } + }, + "representatives_cemented_by_weight": { + "title": "Дифференциал подтверждений", + "tooltip": "Показывает количество веса голосования, которое находится в пределах X подтверждений от ведущего узла. Полезно для понимания, насколько хорошо узлы синхронизированы и выровнены по всей сети" + }, + "representatives_checked_by_weight": { + "title": "Дифференциал блоков", + "tooltip": "Показывает количество веса голосования, которое находится в пределах X блоков от ведущего узла. Полезно для получения представления о том, насколько хорошо распространение блоков синхронизировано в сети" + }, + "representative_delegators": { + "showing_top_delegators": "Показаны 100 лучших делегаторов с минимальным балансом в 1 Nano." + }, + "representative_info": { + "first_seen": "Впервые замечен", + "last_seen": "Последний раз замечен", + "weight_represented": "Представленный вес" + }, + "representative_network": { + "city": "Город", + "isp": "Интернет-провайдер", + "network": "Сеть", + "provider": "Провайдер" + }, + "representative_telemetry": { + "telemetry": "Телеметрия", + "telemetry_timestamp": "Временная метка телеметрии" + }, + "representative_uptime": { + "2m_uptime": "Время работы 2М", + "2w_uptime": "Время работы 2Н", + "3m_uptime": "Время работы 3М", + "current_status": "Текущий статус", + "down": "Не работает", + "down_for": "Не работает в течение", + "operational": "Работает", + "up_for": "Работает в течение", + "warning": "Предупреждение" + }, + "representatives": { + "alias": "Псевдоним", + "cpu_cores": "Ядра ЦПУ", + "cpu_model": "Модель ЦПУ", + "tdp": "TDP (втч)", + "protocol_version": "Протокол", + "last_seen": "Последний раз замечен", + "host_asn": "Хост ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Показывает количество веса голосования на основе локально установленного лимита пропускной способности каждого узла" + }, + "representatives_country_by_weight": { + "title": "Страна" + }, + "representatives_offline": { + "account": "Оффлайн аккаунт", + "last_online": "Последний раз онлайн" + }, + "representatives_page": { + "seo_description": "Исследуйте и анализируйте представителей сети Nano", + "seo_title": "Исследователь представителей Nano", + "telemetry_tab": "Телеметрия", + "weight_distribution_tab": "Распределение веса", + "weight_history_tab": "История веса", + "offline_reps_tab": "Оффлайн представители" + }, + "representatives_provider_by_weight": { + "title": "Хостинг-провайдер" + }, + "representatives_quorum_charts": { + "peers_weight": "Вес пиров", + "quorum_delta": "Дельта кворума", + "title": "Графики кворума", + "trended_weight": "Трендовый вес" + }, + "representatives_search": { + "placeholder": "Фильтр по аккаунту, псевдониму, IP" + }, + "representatives_weight": { + "trended": "Трендовый" + }, + "representatives_weight_chart": { + "title": "Распределение веса по представителям" + }, + "representatives_version_by_weight": { + "title": "Версии" + }, + "roadmap": { + "header": { + "subtitle": "Цели сообщества", + "title": "Планирование" + }, + "seo": { + "description": "Дорожная карта развития и сообщества Nano", + "tags": [ + "дорожная карта", + "nano", + "будущее", + "выпуск", + "дизайн", + "задачи", + "обсуждения", + "сообщество", + "послы", + "менеджеры" + ], + "title": "Дорожная карта" + } + }, + "search_bar": { + "placeholder": "Поиск по адресу / хешу блока" + }, + "uptime": { + "now": "Сейчас", + "days_ago": "дней назад" + } +} diff --git a/locales/tr.json b/locales/tr.json new file mode 100644 index 00000000..210dc246 --- /dev/null +++ b/locales/tr.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Hesap Adresi", + "change_summary": "Özet Değiştir", + "copy_notification": "Hesap adresi kopyalandı", + "seo_description": "Nano temsilci için bilgiler", + "seo_title": "Nano Hesabı", + "telemetry_charts": "Telemetri Grafikleri", + "unopened_description": "Hesap adresi geçerli olsa da, herhangi bir blok gözlemlenmemiştir. Bu hesaba NANO gönderildiyse, fonları almak ve açılış bakiyesi oluşturmak için ilgili bir blok yayınlamak gerekmektedir. Bir hesabın bakiyesi yalnızca hesap sahibi tarafından güncellenebilir çünkü blokları kendi zincirlerine yayınlama yetkileri vardır.", + "unopened_note": "Açılış bloğu zaten yayınlanmışsa, ağ üzerinden yayılması ve nano.community düğümleri tarafından gözlemlenmesi birkaç an alabilir.", + "unopened_title": "Bu hesap henüz açılmadı" + }, + "account_blocks_summary": { + "first_timestamp": "İlk Zaman Damgası", + "last_timestamp": "Son Zaman Damgası", + "max_amount": "Maksimum Miktar", + "min_amount": "Minimum Miktar", + "no_records": "Kayıt Yok", + "receiving_account": "Alıcı Hesap", + "representative_account": "Temsilci Hesabı", + "sending_account": "Gönderen Hesap", + "showing_top_10": "Toplamı azalan sırayla ilk 10 hesap gösteriliyor", + "transactions": "İşlemler" + }, + "account_meta": { + "account_info": "Hesap Bilgisi", + "funding_account": "Finansman Hesabı", + "funding_timestamp": "Finansman Zaman Damgası", + "height": "Yükseklik", + "last_modified": "Son Değiştirilme", + "open_timestamp": "Açılış Zaman Damgası", + "opening_balance": "Açılış Bakiyesi", + "receivable_balance": "Alınabilir Bakiye" + }, + "block_page": { + "amount": "Miktar", + "copy_notification": "Blok hash'i kopyalandı", + "delegated_representative": "Delege Edilmiş Temsilci", + "description": "Açıklama", + "epoch_v1": "Epoch v1 — Hesap zincirlerini eski bloklardan (açık, al, gönder, değiştir) durum bloklarına yükseltildi.", + "epoch_v2": "Epoch v2 - Hesap zincirlerini daha yüksek İş Kanıtı zorluğunu kullanacak şekilde yükseltildi.", + "receiving_account": "Alıcı Hesap", + "section_label": "Blok Hash'i", + "sending_account": "Gönderen Hesap", + "seo_description": "Nano Bloğu ile ilgili bilgiler", + "seo_title": "Nano Blok", + "voting_weight": "Oylama Ağırlığı" + }, + "block_info": { + "block_account": "Blok Hesabı", + "operation": "Operasyon", + "status": "Durum", + "timestamp": "Zaman Damgası" + }, + "block_status": { + "confirmed": "Onaylandı", + "unconfirmed": "Onaylanmadı" + }, + "block_type": { + "change": "Değiştir", + "epoch": "Epoch", + "open": "Aç", + "receive": "Al", + "send": "Gönder" + }, + "common": { + "account_one": "Hesap", + "account_other": "Hesaplar", + "address": "Adres", + "balance": "Bakiye", + "bandwidth_limit": "Bant Genişliği Limiti", + "bandwidth_limit_short": "BG Limiti", + "blocks": "Bloklar", + "blocks_behind": "Geriye Kalan Bloklar", + "blocks_diff_short": "Bloklar Farkı", + "by_online_weight": "Çevrimiçi Ağırlığa Göre", + "clear_filters": "Filtreleri Temizle", + "click_to_copy": "Kopyalamak için tıklayın", + "collapse": "Daralt", + "conf_short": "Onay.", + "conf_diff_short": "Onay Farkı", + "confirmations_behind": "Geriye Kalan Onaylar", + "country": "Ülke", + "delegator_one": "Delege", + "delegator_other": "Delegeler", + "max": "Maks", + "min": "Min", + "offline": "Çevrimdışı", + "online": "Çevrimiçi", + "peers": "Eşler", + "percent_of_total": "Toplamın Yüzdesi", + "port": "Port", + "quorum_delta": "Korum Delta", + "representative_one": "Temsilci", + "representative_other": "Temsilciler", + "show_more": "{{count}} daha fazla göster", + "total": "Toplam", + "unchecked": "Kontrol Edilmemiş", + "unchecked_count": "Kontrol Edilmemiş Sayısı", + "unlimited": "Sınırsız", + "uptime": "Çalışma Süresi", + "version": "Versiyon", + "weight": "Ağırlık" + }, + "delegators": { + "showing_top_delegators": "En üstteki 100 delegatör gösteriliyor, minimum bakiye 1 Nano." + }, + "doc": { + "contributors": "Katkıda Bulunanlar", + "document_not_found": "Belge (veya Hesap) bulunamadı", + "edit_page": "Sayfayı Düzenle", + "help_out": "Yardım Et", + "not_found_404": "404", + "section_link_copied": "Bölüm bağlantısı kopyalandı", + "updated_by": "güncelleyen" + }, + "github_events": { + "action": { + "added_member": "üye eklendi", + "commented_on_commit": "commit üzerine yorum yapıldı", + "commented_on_issue": "sorun üzerine yorum yapıldı", + "commented_on_pr_review": "pr incelemesi üzerine yorum yapıldı", + "created": "{{action}} oluşturuldu", + "deleted": "{{action}} silindi", + "forked": "forklandı", + "issue_action": "{{action}} sorunu", + "made_public": "halka açık yapıldı", + "pr_action": "{{action}} pr", + "pr_review": "pr incelemesi {{title}}", + "published_release": "yayınlandı", + "pushed_commit": "{{ref}}'e commit gönderildi", + "sponsorship_started": "sponsorluk başladı", + "watching_repo": "repo izleniyor" + }, + "events_title": "Geliştirme Olayları" + }, + "ledger": { + "addresses": { + "active_detail": "Aktif, kullanılan benzersiz adreslerin sayısını gösterir. Yeni, oluşturulan adreslerin sayısını gösterir. Yeniden kullanılan, önceki bir günde oluşturulmuş adreslerin kullanıldığını gösterir.", + "active_stats": "Aktif Adres İstatistikleri", + "new_stats": "Yeni Adres İstatistikleri", + "total_number": "Günde kullanılan aktif, yeni ve yeniden kullanılan adreslerin toplam sayısı." + }, + "amounts": { + "total_number": "Blokta belirli bir aralıkta (Nano cinsinden) olan miktarla doğrulanmış gönderi tipi blokların sayısı." + }, + "blocks": { + "change": "Değişiklik Blok İstatistikleri", + "description": "Günde onaylanan blokların sayısı.", + "open": "Açık Blok İstatistikleri", + "receive": "Alma Blok İstatistikleri", + "send": "Gönderme Blok İstatistikleri", + "total": "Toplam Blok İstatistikleri" + }, + "description": "Açıklama", + "usd_transferred": { + "desc_1": "Günde aktarılan toplam değer miktarı (USD cinsinden).", + "desc_2": "Nano/USD'nin günlük kapanış fiyatına ve o gün aktarılan toplam Nano miktarına dayanmaktadır.", + "usd_transferred": "USD Aktarıldı", + "usd_transferred_stats": "USD Aktarılan İstatistikler" + }, + "volume": { + "change_stats": "Değişim İstatistikleri", + "description": "Günde gönderilen toplam miktar (Nano cinsinden) ve günlük toplam oy ağırlığı değişimi.", + "send_stats": "Gönderim İstatistikleri" + } + }, + "ledger_page": { + "addresses_tab": "Adresler", + "amounts_tab": "Miktarlar", + "blocks_tab": "Bloklar", + "seo_description": "Nano defterinin zincir içi metrikleri ve analizleri", + "seo_title": "Nano Defter Analizi", + "value_transferred_tab": "Aktarılan Değer", + "volume_tab": "Hacim" + }, + "menu": { + "account_setup": "Hesap Kurulumu", + "acquiring": "Edinme", + "advantages": "Avantajlar", + "attack_vectors": "Saldırı Vektörleri", + "basics": "Temeller", + "best_practices": "En İyi Uygulamalar", + "choosing_a_rep": "Temsilci Seçimi", + "challenges": "Zorluklar", + "communities": "Topluluklar", + "contribution_guide": "Katkı Rehberi", + "design": "Tasarım", + "developer_discussions": "Geliştirici Tartışmaları", + "developers": "Geliştiriciler", + "documentation": "Dokümantasyon", + "faqs": "SSS", + "get_involved": "Katıl", + "get_support": "Destek Al", + "getting_started": "Başlarken", + "glossary": "Sözlük", + "guides": "Rehberler", + "history": "Tarih", + "home": "Ana Sayfa", + "how_it_works": "Nasıl Çalışır", + "integrations": "Entegrasyonlar", + "introduction": "Giriş", + "investment_thesis": "Yatırım Tezi", + "learn": "Öğren", + "ledger": "Defter", + "misconceptions": "Yanlış Anlamalar", + "overview": "Genel Bakış", + "planning": "Planlama 👾", + "privacy": "Gizlilik", + "protocol": "Protokol", + "running_a_node": "Bir Düğüm Çalıştırmak", + "security": "Güvenlik", + "stats": "İstatistikler", + "storing": "Saklama", + "telemetry": "Telemetri", + "topics": "Konular", + "using": "Kullanım", + "why_it_matters": "Neden Önemli" + }, + "network": { + "backlog_text": "Onaylanmayı bekleyen işlemlerin medyan sayısı $(network.pr_text)", + "censor_text": "İşlemleri sansürlemek veya ağı durdurmak için gereken minimum temsilci sayısı", + "confirm_text": "İşlemleri onaylamak için gereken minimum temsilci sayısı", + "confirmations": "Onaylar (24s)", + "confirmations_text": "Son 24 saatte ağ tarafından onaylanan toplam işlem sayısı", + "energy_text": "Toplanan CPU model bilgilerine dayanarak canlı ağın CPU enerji kullanımının tahmini. Tahmin, tüm çekirdekler aktifken ve üretici tarafından tanımlanan yüksek karmaşıklıktaki iş yükü altında işlemcinin ortalama olarak dağıttığı watt cinsinden ortalama güç olan CPU TDP'sine dayanmaktadır", + "energy_usage": "Enerji Kullanımı (TDP) (24s)", + "fee_text": "Nano ağı ücretsiz olarak işlemektedir", + "nano_ticker": "NanoTicker", + "online_stake": "Çevrimiçi Hisse", + "principal_reps": "Başlıca Temsilciler", + "pr_text": "ağın başlıca temsilcileri arasında gözlemlenen: çevrimiçi oy ağırlığının %0.1'inden fazlasına sahip olan oy verme düğümleri", + "reps_to_censor": "Sansür veya Duraklatma için Temsilciler", + "reps_to_confirm": "Onay için Temsilciler", + "settlement": "Yerleşim (24s)", + "settlement_text": "Son 24 saatte ağ tarafından yerleştirilen toplam değer miktarı", + "speed_text": "Bir test işleminin onaylanması için gereken süre milisaniye cinsinden", + "stake_text": "Oy kullanmada aktif olarak yer alan delegasyonun Nano ağırlık yüzdesi", + "stats_title": "Ağ İstatistikleri", + "total_reps": "Toplam Temsilciler (24s)", + "tx_backlog": "Tx Bekleme Listesi", + "tx_fees": "Tx Ücretleri (24s)", + "tx_speed": "Tx Hızı", + "tx_throughput": "Tx İşlem Kapasitesi", + "throughput_text": "Son dakikada saniye başına onaylanan işlemlerin medyan sayısı $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano Vakfı", + "top": "En İyi", + "trending": "Trend" + }, + "representative_alerts": { + "table_header": { + "behind": "Geri Kalan", + "issue": "Sorun", + "last_online": "Son Çevrimiçi", + "percent_online_weight": "% Çevrimiçi Ağırlık", + "representative": "Temsilci" + }, + "tooltip": { + "behind": "Temsilci geride kaldı veya önyükleme yapıyor. Kesim noktası, 95. persentilin ötesinde bir çimento sayısıdır. (telemetri aracılığıyla)", + "low_uptime": "Temsilci son 28 günde %25'ten fazla çevrimdışıydı.", + "offline": "Temsilci oy kullanmayı durdurdu ve çevrimdışı görünüyor.", + "overweight": "Temsilcinin 3M Nano oy ağırlığından fazlası var. Delegelerin ağın direncini ve değerini artırmak için ağırlığı dağıtmayı düşünmeleri gerekir." + }, + "type": { + "behind": "Geri Kalan", + "low_uptime": "Düşük Çalışma Süresi", + "offline": "Çevrimdışı", + "overweight": "Aşırı Ağırlık" + } + }, + "representatives_cemented_by_weight": { + "title": "Onay Farkı", + "tooltip": "Lider düğümden X sayıda onay içinde olan oy ağırlığının miktarını gösterir. Ağın ne kadar iyi senkronize edildiğini ve düğümler arasında ne kadar hizalandığını bilmek için yararlıdır" + }, + "representatives_checked_by_weight": { + "title": "Blok Farkı", + "tooltip": "Lider düğümden X sayıda blok içinde olan oy ağırlığının miktarını gösterir. Ağ içinde blok yayılımının ne kadar senkronize olduğunu anlamak için yararlıdır" + }, + "representative_delegators": { + "showing_top_delegators": "Minimum 1 Nano bakiyesi olan en iyi 100 delegatör gösteriliyor." + }, + "representative_info": { + "first_seen": "İlk Görülme", + "last_seen": "Son Görülme", + "weight_represented": "Temsil Edilen Ağırlık" + }, + "representative_network": { + "city": "Şehir", + "isp": "ISS", + "network": "Ağ", + "provider": "Sağlayıcı" + }, + "representative_telemetry": { + "telemetry": "Telemetri", + "telemetry_timestamp": "Telemetri Zaman Damgası" + }, + "representative_uptime": { + "2m_uptime": "2A Çalışma Süresi", + "2w_uptime": "2H Çalışma Süresi", + "3m_uptime": "3A Çalışma Süresi", + "current_status": "Mevcut Durum", + "down": "Çalışmıyor", + "down_for": "İçin Çalışmıyor", + "operational": "Operasyonel", + "up_for": "İçin Çalışıyor", + "warning": "Uyarı" + }, + "representatives": { + "alias": "Takma Ad", + "cpu_cores": "CPU Çekirdekleri", + "cpu_model": "CPU Modeli", + "tdp": "TDP (wH)", + "protocol_version": "Protokol", + "last_seen": "Son Görülme", + "host_asn": "Host ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Her düğüm tarafından yerel olarak ayarlanan bant genişliği limitine göre oy ağırlığının miktarını gösterir" + }, + "representatives_country_by_weight": { + "title": "Ülke" + }, + "representatives_offline": { + "account": "Çevrimdışı Hesap", + "last_online": "Son Çevrimiçi" + }, + "representatives_page": { + "seo_description": "Nano ağ temsilcilerini keşfedin ve analiz edin", + "seo_title": "Nano Temsilcileri Gezgini", + "telemetry_tab": "Telemetri", + "weight_distribution_tab": "Ağırlık Dağılımı", + "weight_history_tab": "Ağırlık Geçmişi", + "offline_reps_tab": "Çevrimdışı Temsilciler" + }, + "representatives_provider_by_weight": { + "title": "Barındırma Sağlayıcısı" + }, + "representatives_quorum_charts": { + "peers_weight": "Eşlerin Ağırlığı", + "quorum_delta": "Korum Farkı", + "title": "Korum Grafikleri", + "trended_weight": "Trend Olan Ağırlık" + }, + "representatives_search": { + "placeholder": "Hesap, takma ad, ip ile filtrele" + }, + "representatives_weight": { + "trended": "Trend Olan" + }, + "representatives_weight_chart": { + "title": "Temsilciye Göre Ağırlık Dağılımı" + }, + "representatives_version_by_weight": { + "title": "Versiyonlar" + }, + "roadmap": { + "header": { + "subtitle": "Topluluk hedefleri", + "title": "Planlama" + }, + "seo": { + "description": "Nano geliştirme & topluluk yol haritası", + "tags": [ + "yol haritası", + "nano", + "gelecek", + "sürüm", + "tasarım", + "görevler", + "tartışmalar", + "topluluk", + "elçiler", + "yöneticiler" + ], + "title": "Yol Haritası" + } + }, + "search_bar": { + "placeholder": "Adres / Blok Hash ile Ara" + }, + "uptime": { + "now": "Şimdi", + "days_ago": "gün önce" + } +} diff --git a/locales/vi.json b/locales/vi.json new file mode 100644 index 00000000..5616cd8f --- /dev/null +++ b/locales/vi.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "Địa chỉ tài khoản", + "change_summary": "Thay đổi tóm tắt", + "copy_notification": "Đã sao chép địa chỉ tài khoản", + "seo_description": "Thông tin cho đại diện nano", + "seo_title": "Tài khoản Nano", + "telemetry_charts": "Biểu đồ Telemetry", + "unopened_description": "Mặc dù địa chỉ tài khoản là hợp lệ, không có khối nào được quan sát. Nếu NANO đã được gửi đến tài khoản này, nó vẫn cần phải xuất bản một khối tương ứng để nhận tiền và thiết lập một số dư mở. Số dư của một tài khoản chỉ có thể được cập nhật bởi chủ sở hữu tài khoản vì họ là người duy nhất có thể xuất bản các khối vào chuỗi của họ.", + "unopened_note": "Nếu một khối mở đã được xuất bản, có thể mất một vài phút để lan truyền qua mạng và được các nút nano.community quan sát.", + "unopened_title": "Tài khoản này chưa được mở" + }, + "account_blocks_summary": { + "first_timestamp": "Dấu thời gian đầu tiên", + "last_timestamp": "Dấu thời gian cuối cùng", + "max_amount": "Số lượng tối đa", + "min_amount": "Số lượng tối thiểu", + "no_records": "Không có bản ghi", + "receiving_account": "Tài khoản nhận", + "representative_account": "Tài khoản đại diện", + "sending_account": "Tài khoản gửi", + "showing_top_10": "Hiển thị 10 tài khoản hàng đầu theo tổng giảm dần", + "transactions": "Giao dịch" + }, + "account_meta": { + "account_info": "Thông tin tài khoản", + "funding_account": "Tài khoản tài trợ", + "funding_timestamp": "Dấu thời gian tài trợ", + "height": "Chiều cao", + "last_modified": "Lần chỉnh sửa cuối", + "open_timestamp": "Mở dấu thời gian", + "opening_balance": "Số dư mở", + "receivable_balance": "Số dư có thể nhận" + }, + "block_page": { + "amount": "Số lượng", + "copy_notification": "Đã sao chép hash khối", + "delegated_representative": "Đại diện được ủy quyền", + "description": "Mô tả", + "epoch_v1": "Kỷ nguyên v1 — Nâng cấp chuỗi tài khoản từ các khối di sản (mở, nhận, gửi, thay đổi) sang các khối trạng thái.", + "epoch_v2": "Kỷ nguyên v2 - Nâng cấp chuỗi tài khoản để sử dụng độ khó Proof-of-Work cao hơn.", + "receiving_account": "Tài khoản nhận", + "section_label": "Hash khối", + "sending_account": "Tài khoản gửi", + "seo_description": "Thông tin liên quan đến một khối Nano", + "seo_title": "Khối Nano", + "voting_weight": "Trọng số bỏ phiếu" + }, + "block_info": { + "block_account": "Tài khoản khối", + "operation": "Hoạt động", + "status": "Trạng thái", + "timestamp": "Dấu thời gian" + }, + "block_status": { + "confirmed": "Đã xác nhận", + "unconfirmed": "Chưa xác nhận" + }, + "block_type": { + "change": "Thay đổi", + "epoch": "Kỷ nguyên", + "open": "Mở", + "receive": "Nhận", + "send": "Gửi" + }, + "common": { + "account_one": "Tài khoản", + "account_other": "Các tài khoản", + "address": "Địa chỉ", + "balance": "Số dư", + "bandwidth_limit": "Giới hạn băng thông", + "bandwidth_limit_short": "Giới hạn BW", + "blocks": "Khối", + "blocks_behind": "Khối phía sau", + "blocks_diff_short": "Khác biệt khối", + "by_online_weight": "Theo trọng số trực tuyến", + "clear_filters": "Xóa bộ lọc", + "click_to_copy": "Nhấn để sao chép", + "collapse": "Thu gọn", + "conf_short": "Xác nhận.", + "conf_diff_short": "Khác biệt xác nhận", + "confirmations_behind": "Xác nhận phía sau", + "country": "Quốc gia", + "delegator_one": "Người ủy quyền", + "delegator_other": "Người ủy quyền", + "max": "Tối đa", + "min": "Tối thiểu", + "offline": "Ngoại tuyến", + "online": "Trực tuyến", + "peers": "Đối tác", + "percent_of_total": "% của tổng", + "port": "Cổng", + "quorum_delta": "Delta quorum", + "representative_one": "Đại diện", + "representative_other": "Các đại diện", + "show_more": "Hiển thị thêm {{count}}", + "total": "Tổng", + "unchecked": "Chưa kiểm tra", + "unchecked_count": "Số lượng chưa kiểm tra", + "unlimited": "Không giới hạn", + "uptime": "Thời gian hoạt động", + "version": "Phiên bản", + "weight": "Trọng lượng" + }, + "delegators": { + "showing_top_delegators": "Hiển thị 100 người ủy quyền hàng đầu với số dư tối thiểu là 1 Nano." + }, + "doc": { + "contributors": "Người đóng góp", + "document_not_found": "Tài liệu (hoặc Tài khoản) không tìm thấy", + "edit_page": "Chỉnh sửa trang", + "help_out": "Giúp đỡ", + "not_found_404": "404", + "section_link_copied": "Liên kết mục đã được sao chép", + "updated_by": "cập nhật bởi" + }, + "github_events": { + "action": { + "added_member": "đã thêm thành viên", + "commented_on_commit": "đã bình luận về commit", + "commented_on_issue": "đã bình luận về vấn đề", + "commented_on_pr_review": "đã bình luận về đánh giá pr", + "created": "đã tạo {{action}}", + "deleted": "đã xóa {{action}}", + "forked": "đã fork", + "issue_action": "{{action}} vấn đề", + "made_public": "đã công khai", + "pr_action": "{{action}} pr", + "pr_review": "đánh giá pr {{title}}", + "published_release": "đã xuất bản phát hành", + "pushed_commit": "đã đẩy commit vào {{ref}}", + "sponsorship_started": "tài trợ bắt đầu", + "watching_repo": "đang theo dõi repo" + }, + "events_title": "Sự kiện Phát triển" + }, + "ledger": { + "addresses": { + "active_detail": "Hoạt động hiển thị số lượng địa chỉ duy nhất được sử dụng. Mới hiển thị số lượng địa chỉ được tạo. Tái sử dụng hiển thị số lượng địa chỉ được sử dụng đã được tạo vào ngày trước đó.", + "active_stats": "Thống kê Địa chỉ Hoạt động", + "new_stats": "Thống kê Địa chỉ Mới", + "total_number": "Tổng số lượng địa chỉ hoạt động, mới và tái sử dụng được sử dụng mỗi ngày." + }, + "amounts": { + "total_number": "Số lượng các khối loại gửi được xác nhận mỗi ngày mà số lượng trong khối nằm trong phạm vi cho trước (tính bằng Nano)" + }, + "blocks": { + "change": "Thống kê Khối Thay đổi", + "description": "Số lượng khối được xác nhận mỗi ngày.", + "open": "Thống kê Khối Mở", + "receive": "Thống kê Khối Nhận", + "send": "Thống kê Khối Gửi", + "total": "Thống kê Tổng Khối" + }, + "description": "Mô tả", + "usd_transferred": { + "desc_1": "Tổng số lượng giá trị được chuyển (tính bằng USD) mỗi ngày.", + "desc_2": "Dựa trên giá đóng cửa hàng ngày của Nano/USD và tổng số lượng Nano được chuyển trong ngày đó.", + "usd_transferred": "USD Đã Chuyển", + "usd_transferred_stats": "Thống kê USD Đã Chuyển" + }, + "volume": { + "change_stats": "Thống kê Thay đổi", + "description": "Tổng số lượng gửi (tính bằng Nano) và tổng số lượng trọng lượng bỏ phiếu thay đổi mỗi ngày.", + "send_stats": "Thống kê Gửi" + } + }, + "ledger_page": { + "addresses_tab": "Địa chỉ", + "amounts_tab": "Số lượng", + "blocks_tab": "Khối", + "seo_description": "Các chỉ số và phân tích trên chuỗi của sổ cái Nano", + "seo_title": "Phân tích Sổ cái Nano", + "value_transferred_tab": "Giá trị Chuyển nhượng", + "volume_tab": "Khối lượng" + }, + "menu": { + "account_setup": "Thiết lập Tài khoản", + "acquiring": "Đang Thu thập", + "advantages": "Ưu điểm", + "attack_vectors": "Vector Tấn công", + "basics": "Cơ bản", + "best_practices": "Phương pháp Tốt nhất", + "choosing_a_rep": "Chọn một Đại diện", + "challenges": "Thách thức", + "communities": "Cộng đồng", + "contribution_guide": "Hướng dẫn Đóng góp", + "design": "Thiết kế", + "developer_discussions": "Thảo luận của Nhà phát triển", + "developers": "Nhà phát triển", + "documentation": "Tài liệu", + "faqs": "Câu hỏi thường gặp", + "get_involved": "Tham gia", + "get_support": "Nhận Hỗ trợ", + "getting_started": "Bắt đầu", + "glossary": "Thuật ngữ", + "guides": "Hướng dẫn", + "history": "Lịch sử", + "home": "Trang chủ", + "how_it_works": "Cách nó hoạt động", + "integrations": "Tích hợp", + "introduction": "Giới thiệu", + "investment_thesis": "Luận án Đầu tư", + "learn": "Học", + "ledger": "Sổ cái", + "misconceptions": "Hiểu lầm", + "overview": "Tổng quan", + "planning": "Lập kế hoạch 👾", + "privacy": "Riêng tư", + "protocol": "Giao thức", + "running_a_node": "Chạy một nút", + "security": "Bảo mật", + "stats": "Thống kê", + "storing": "Lưu trữ", + "telemetry": "Telemetry", + "topics": "Chủ đề", + "using": "Sử dụng", + "why_it_matters": "Tại sao nó quan trọng" + }, + "network": { + "backlog_text": "Số trung bình giao dịch chờ được xác nhận $(network.pr_text)", + "censor_text": "Số lượng đại diện tối thiểu cần thiết để kiểm duyệt giao dịch hoặc làm chậm mạng", + "confirm_text": "Số lượng đại diện tối thiểu cần thiết để xác nhận giao dịch", + "confirmations": "Xác nhận (24h)", + "confirmations_text": "Tổng số giao dịch được mạng xác nhận trong 24 giờ qua", + "energy_text": "Ước lượng sử dụng năng lượng CPU của mạng trực tiếp của các Đại diện Chính dựa trên thông tin mô hình CPU đã thu thập. Ước lượng dựa trên TDP CPU, là công suất trung bình, tính bằng watt, mà bộ xử lý tản nhiệt khi hoạt động ở tần số cơ bản với tất cả các lõi hoạt động dưới tải công việc phức tạp được định nghĩa bởi nhà sản xuất", + "energy_usage": "Sử dụng Năng lượng (TDP) (24h)", + "fee_text": "Mạng Nano hoạt động không mất phí", + "nano_ticker": "NanoTicker", + "online_stake": "Cổ phần Trực tuyến", + "principal_reps": "Đại diện Chính", + "pr_text": "như quan sát trên các đại diện chính của mạng: các nút bỏ phiếu với hơn 0.1% trọng số bỏ phiếu trực tuyến được ủy quyền cho họ", + "reps_to_censor": "Đại diện để Kiểm duyệt hoặc Làm chậm", + "reps_to_confirm": "Đại diện để Xác nhận", + "settlement": "Giải quyết (24h)", + "settlement_text": "Tổng số giá trị được mạng giải quyết trong 24 giờ qua", + "speed_text": "Thời gian tính bằng mili giây để một giao dịch thử nghiệm được xác nhận", + "stake_text": "Phần trăm trọng số Nano được ủy quyền tham gia tích cực trong việc bỏ phiếu", + "stats_title": "Thống kê Mạng", + "total_reps": "Tổng số Đại diện (24h)", + "tx_backlog": "Tx Backlog", + "tx_fees": "Phí Tx (24h)", + "tx_speed": "Tốc độ Tx", + "tx_throughput": "Lượng xử lý Tx", + "throughput_text": "Số lượng giao dịch trung bình được xác nhận mỗi giây trong phút cuối cùng $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Quỹ Nano", + "top": "Hàng đầu", + "trending": "Xu hướng" + }, + "representative_alerts": { + "table_header": { + "behind": "Phía sau", + "issue": "Vấn đề", + "last_online": "Lần trực tuyến cuối", + "percent_online_weight": "% Trọng số trực tuyến", + "representative": "Đại diện" + }, + "tooltip": { + "behind": "Đại diện đã tụt hậu hoặc đang khởi động. Ngưỡng là số lượng đã củng cố vượt qua phần trăm thứ 95. (qua telemetry)", + "low_uptime": "Đại diện đã ngoại tuyến hơn 25% trong 28 ngày qua.", + "offline": "Đại diện đã ngừng bỏ phiếu và dường như ngoại tuyến.", + "overweight": "Đại diện có trọng số bỏ phiếu vượt quá 3M Nano. Người ủy quyền nên xem xét phân phối trọng số để cải thiện sự kiên cường và giá trị của mạng." + }, + "type": { + "behind": "Phía sau", + "low_uptime": "Thời gian hoạt động thấp", + "offline": "Ngoại tuyến", + "overweight": "Quá tải" + } + }, + "representatives_cemented_by_weight": { + "title": "Chênh lệch Xác nhận", + "tooltip": "Hiển thị số lượng trọng số bỏ phiếu nằm trong X số lượng xác nhận từ nút dẫn đầu. Hữu ích trong việc biết các nút trên mạng đồng bộ và căn chỉnh như thế nào" + }, + "representatives_checked_by_weight": { + "title": "Chênh lệch Khối", + "tooltip": "Hiển thị số lượng trọng số bỏ phiếu nằm trong X số lượng khối từ nút dẫn đầu. Hữu ích để nhận biết sự đồng bộ phát tán khối trong mạng như thế nào" + }, + "representative_delegators": { + "showing_top_delegators": "Hiển thị 100 người ủy quyền hàng đầu với số dư tối thiểu là 1 Nano." + }, + "representative_info": { + "first_seen": "Nhìn thấy lần đầu", + "last_seen": "Nhìn thấy lần cuối", + "weight_represented": "Trọng số đại diện" + }, + "representative_network": { + "city": "Thành phố", + "isp": "ISP", + "network": "Mạng", + "provider": "Nhà cung cấp" + }, + "representative_telemetry": { + "telemetry": "Telemetry", + "telemetry_timestamp": "Dấu thời gian Telemetry" + }, + "representative_uptime": { + "2m_uptime": "Thời gian hoạt động 2M", + "2w_uptime": "Thời gian hoạt động 2W", + "3m_uptime": "Thời gian hoạt động 3M", + "current_status": "Trạng thái hiện tại", + "down": "Hỏng", + "down_for": "Hỏng trong", + "operational": "Hoạt động", + "up_for": "Hoạt động trong", + "warning": "Cảnh báo" + }, + "representatives": { + "alias": "Bí danh", + "cpu_cores": "Lõi CPU", + "cpu_model": "Mô hình CPU", + "tdp": "TDP (wH)", + "protocol_version": "Giao thức", + "last_seen": "Nhìn thấy lần cuối", + "host_asn": "Host ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "Hiển thị số lượng trọng số bỏ phiếu dựa trên giới hạn băng thông được thiết lập cục bộ bởi mỗi nút" + }, + "representatives_country_by_weight": { + "title": "Quốc gia" + }, + "representatives_offline": { + "account": "Tài khoản Ngoại tuyến", + "last_online": "Lần trực tuyến cuối" + }, + "representatives_page": { + "seo_description": "Khám phá và phân tích các đại diện mạng Nano", + "seo_title": "Trình khám phá Đại diện Nano", + "telemetry_tab": "Telemetry", + "weight_distribution_tab": "Phân phối Trọng số", + "weight_history_tab": "Lịch sử Trọng số", + "offline_reps_tab": "Đại diện Ngoại tuyến" + }, + "representatives_provider_by_weight": { + "title": "Nhà cung cấp Hosting" + }, + "representatives_quorum_charts": { + "peers_weight": "Trọng số Peers", + "quorum_delta": "Quorum Delta", + "title": "Biểu đồ Quorum", + "trended_weight": "Trọng số Xu hướng" + }, + "representatives_search": { + "placeholder": "Lọc theo tài khoản, bí danh, ip" + }, + "representatives_weight": { + "trended": "Xu hướng" + }, + "representatives_weight_chart": { + "title": "Phân phối Trọng số theo Đại diện" + }, + "representatives_version_by_weight": { + "title": "Phiên bản" + }, + "roadmap": { + "header": { + "subtitle": "Mục tiêu cộng đồng", + "title": "Kế hoạch" + }, + "seo": { + "description": "Lộ trình phát triển & cộng đồng Nano", + "tags": [ + "lộ trình", + "nano", + "tương lai", + "phát hành", + "thiết kế", + "nhiệm vụ", + "thảo luận", + "cộng đồng", + "đại sứ", + "quản lý" + ], + "title": "Lộ trình" + } + }, + "search_bar": { + "placeholder": "Tìm kiếm theo Địa chỉ / Hash Khối" + }, + "uptime": { + "now": "Bây giờ", + "days_ago": "ngày trước" + } +} diff --git a/locales/zh.json b/locales/zh.json new file mode 100644 index 00000000..a113f462 --- /dev/null +++ b/locales/zh.json @@ -0,0 +1,387 @@ +{ + "account_page": { + "address": "账户地址", + "change_summary": "更改摘要", + "copy_notification": "账户地址已复制", + "seo_description": "纳米代表的信息", + "seo_title": "纳米账户", + "telemetry_charts": "遥测图表", + "unopened_description": "尽管账户地址有效,但尚未观察到任何区块。如果已向此账户发送了NANO,则仍需发布相应的区块以接收资金并建立开户余额。账户余额只能由账户持有者更新,因为只有他们才能向其链发布区块。", + "unopened_note": "如果已经发布了开户区块,可能需要一些时间才能通过网络传播并被nano.community节点观察到。", + "unopened_title": "此账户尚未开通" + }, + "account_blocks_summary": { + "first_timestamp": "首次时间戳", + "last_timestamp": "最后时间戳", + "max_amount": "最大金额", + "min_amount": "最小金额", + "no_records": "无记录", + "receiving_account": "接收账户", + "representative_account": "代表账户", + "sending_account": "发送账户", + "showing_top_10": "按总额降序显示前10个账户", + "transactions": "交易次数" + }, + "account_meta": { + "account_info": "账户信息", + "funding_account": "资金账户", + "funding_timestamp": "资金时间戳", + "height": "高度", + "last_modified": "最后修改", + "open_timestamp": "开户时间戳", + "opening_balance": "开户余额", + "receivable_balance": "应收余额" + }, + "block_page": { + "amount": "金额", + "copy_notification": "区块哈希已复制", + "delegated_representative": "委托代表", + "description": "描述", + "epoch_v1": "纪元v1 - 将账户链从传统区块(开户、接收、发送、更改)升级到状态区块。", + "epoch_v2": "纪元v2 - 将账户链升级以使用更高的工作量证明难度。", + "receiving_account": "接收账户", + "section_label": "区块哈希", + "sending_account": "发送账户", + "seo_description": "与纳米区块相关的信息", + "seo_title": "纳米区块", + "voting_weight": "投票权重" + }, + "block_info": { + "block_account": "区块账户", + "operation": "操作", + "status": "状态", + "timestamp": "时间戳" + }, + "block_status": { + "confirmed": "已确认", + "unconfirmed": "未确认" + }, + "block_type": { + "change": "更改", + "epoch": "纪元", + "open": "开户", + "receive": "接收", + "send": "发送" + }, + "common": { + "account_one": "账户", + "account_other": "账户", + "address": "地址", + "balance": "余额", + "bandwidth_limit": "带宽限制", + "bandwidth_limit_short": "带宽限制", + "blocks": "区块", + "blocks_behind": "区块落后", + "blocks_diff_short": "区块差异", + "by_online_weight": "按在线权重", + "clear_filters": "清除过滤器", + "click_to_copy": "点击复制", + "collapse": "折叠", + "conf_short": "确认", + "conf_diff_short": "确认差异", + "confirmations_behind": "确认落后", + "country": "国家", + "delegator_one": "委托人", + "delegator_other": "委托人", + "max": "最大", + "min": "最小", + "offline": "离线", + "online": "在线", + "peers": "节点", + "percent_of_total": "总百分比", + "port": "端口", + "quorum_delta": "法定人数差", + "representative_one": "代表", + "representative_other": "代表们", + "show_more": "显示更多 {{count}}", + "total": "总计", + "unchecked": "未检查", + "unchecked_count": "未检查计数", + "unlimited": "无限", + "uptime": "运行时间", + "version": "版本", + "weight": "权重" + }, + "delegators": { + "showing_top_delegators": "显示前100名代理人,最低余额为1 Nano。" + }, + "doc": { + "contributors": "贡献者", + "document_not_found": "未找到文档(或账户)", + "edit_page": "编辑页面", + "help_out": "提供帮助", + "not_found_404": "404", + "section_link_copied": "已复制章节链接", + "updated_by": "更新者" + }, + "github_events": { + "action": { + "added_member": "已添加成员", + "commented_on_commit": "对提交进行了评论", + "commented_on_issue": "对问题进行了评论", + "commented_on_pr_review": "对PR审查进行了评论", + "created": "已创建 {{action}}", + "deleted": "已删除 {{action}}", + "forked": "已分叉", + "issue_action": "{{action}} 问题", + "made_public": "已公开", + "pr_action": "{{action}} PR", + "pr_review": "PR审查 {{title}}", + "published_release": "已发布发布", + "pushed_commit": "推送提交到 {{ref}}", + "sponsorship_started": "赞助已开始", + "watching_repo": "正在观看仓库" + }, + "events_title": "开发事件" + }, + "ledger": { + "addresses": { + "active_detail": "活跃显示每天使用的唯一地址数量。新显示创建的地址数量。重用显示在前一天创建并使用的地址数量。", + "active_stats": "活跃地址统计", + "new_stats": "新地址统计", + "total_number": "每天使用的活跃、新建和重用地址的总数。" + }, + "amounts": { + "total_number": "每天确认的发送类型区块的数量,其中区块中的金额在给定范围内(以Nano为单位)" + }, + "blocks": { + "change": "更改区块统计", + "description": "每天确认的区块数量。", + "open": "开户区块统计", + "receive": "接收区块统计", + "send": "发送区块统计", + "total": "总区块统计" + }, + "description": "描述", + "usd_transferred": { + "desc_1": "每天转移的价值总额(以USD计)。", + "desc_2": "基于Nano/USD的每日收盘价和当天转移的Nano总量。", + "usd_transferred": "转移的USD", + "usd_transferred_stats": "转移的USD统计" + }, + "volume": { + "change_stats": "更改统计", + "description": "每天发送的总金额(以Nano为单位)和总投票权重变化量。", + "send_stats": "发送统计" + } + }, + "ledger_page": { + "addresses_tab": "地址", + "amounts_tab": "金额", + "blocks_tab": "区块", + "seo_description": "Nano账本的链上指标和分析", + "seo_title": "Nano账本分析", + "value_transferred_tab": "转移的价值", + "volume_tab": "体积" + }, + "menu": { + "account_setup": "账户设置", + "acquiring": "获取", + "advantages": "优势", + "attack_vectors": "攻击向量", + "basics": "基础", + "best_practices": "最佳实践", + "choosing_a_rep": "选择代表", + "challenges": "挑战", + "communities": "社区", + "contribution_guide": "贡献指南", + "design": "设计", + "developer_discussions": "开发者讨论", + "developers": "开发者", + "documentation": "文档", + "faqs": "常见问题", + "get_involved": "参与", + "get_support": "获取支持", + "getting_started": "入门", + "glossary": "词汇表", + "guides": "指南", + "history": "历史", + "home": "首页", + "how_it_works": "它是如何工作的", + "integrations": "集成", + "introduction": "介绍", + "investment_thesis": "投资论文", + "learn": "学习", + "ledger": "账本", + "misconceptions": "误解", + "overview": "概览", + "planning": "规划 👾", + "privacy": "隐私", + "protocol": "协议", + "running_a_node": "运行一个节点", + "security": "安全", + "stats": "统计", + "storing": "存储", + "telemetry": "遥测", + "topics": "主题", + "using": "使用", + "why_it_matters": "为什么这很重要" + }, + "network": { + "backlog_text": "等待确认的交易中位数 $(network.pr_text)", + "censor_text": "需要最少的代表数量来审查交易或阻塞网络", + "confirm_text": "需要最少的代表数量来确认交易", + "confirmations": "确认(24小时)", + "confirmations_text": "网络在过去24小时内确认的交易总数", + "energy_text": "根据收集的CPU型号信息估算的主要代表的实时网络CPU能耗。该估算基于CPU TDP,即处理器在制造商定义的高复杂度工作负载下,所有核心在基础频率下运行时的平均功率(瓦特)", + "energy_usage": "能源使用(TDP)(24小时)", + "fee_text": "Nano网络无需费用运作", + "nano_ticker": "Nano行情", + "online_stake": "在线股份", + "principal_reps": "主要代表", + "pr_text": "在网络的主要代表中观察到:被委托超过0.1%在线投票权的投票节点", + "reps_to_censor": "审查或阻塞的代表", + "reps_to_confirm": "确认的代表", + "settlement": "结算(24小时)", + "settlement_text": "网络在过去24小时内结算的总价值", + "speed_text": "测试交易被确认的毫秒数", + "stake_text": "积极参与投票的委托Nano权重的百分比", + "stats_title": "网络统计", + "total_reps": "总代表(24小时)", + "tx_backlog": "交易积压", + "tx_fees": "交易费(24小时)", + "tx_speed": "交易速度", + "tx_throughput": "交易吞吐量", + "throughput_text": "在最后一分钟内每秒确认的交易中位数 $(network.pr_text)" + }, + "posts": { + "nano_foundation": "Nano基金会", + "top": "顶部", + "trending": "趋势" + }, + "representative_alerts": { + "table_header": { + "behind": "落后", + "issue": "问题", + "last_online": "最后在线", + "percent_online_weight": "% 在线权重", + "representative": "代表" + }, + "tooltip": { + "behind": "代表已落后或正在引导。截止点是超过第95百分位的固化计数。(通过遥测)", + "low_uptime": "代表在过去28天内超过25%的时间离线。", + "offline": "代表已停止投票并似乎离线。", + "overweight": "代表拥有超过3M Nano的投票权重。委托人应考虑分散权重以提高网络的弹性和价值。" + }, + "type": { + "behind": "落后", + "low_uptime": "低正常运行时间", + "offline": "离线", + "overweight": "超重" + } + }, + "representatives_cemented_by_weight": { + "title": "确认差异", + "tooltip": "显示距离领先节点X个确认内的投票权重量。有助于了解网络各节点的同步程度和一致性" + }, + "representatives_checked_by_weight": { + "title": "区块差异", + "tooltip": "显示距离领先节点X个区块内的投票权重量。用于了解网络内区块传播的同步程度" + }, + "representative_delegators": { + "showing_top_delegators": "显示前100个委托人,最低余额为1 Nano。" + }, + "representative_info": { + "first_seen": "首次出现", + "last_seen": "最后出现", + "weight_represented": "代表的权重" + }, + "representative_network": { + "city": "城市", + "isp": "ISP", + "network": "网络", + "provider": "提供者" + }, + "representative_telemetry": { + "telemetry": "遥测", + "telemetry_timestamp": "遥测时间戳" + }, + "representative_uptime": { + "2m_uptime": "2M正常运行时间", + "2w_uptime": "2W正常运行时间", + "3m_uptime": "3M正常运行时间", + "current_status": "当前状态", + "down": "下线", + "down_for": "下线时间", + "operational": "运行中", + "up_for": "上线时间", + "warning": "警告" + }, + "representatives": { + "alias": "别名", + "cpu_cores": "CPU核心", + "cpu_model": "CPU型号", + "tdp": "TDP (wH)", + "protocol_version": "协议", + "last_seen": "最后出现", + "host_asn": "主机ASN" + }, + "representatives_bandwidth_by_weight": { + "tooltip": "根据每个节点本地设置的带宽限制显示投票权重量" + }, + "representatives_country_by_weight": { + "title": "国家" + }, + "representatives_offline": { + "account": "离线账户", + "last_online": "最后在线" + }, + "representatives_page": { + "seo_description": "探索和分析Nano网络代表", + "seo_title": "Nano代表浏览器", + "telemetry_tab": "遥测", + "weight_distribution_tab": "权重分布", + "weight_history_tab": "权重历史", + "offline_reps_tab": "离线代表" + }, + "representatives_provider_by_weight": { + "title": "托管提供者" + }, + "representatives_quorum_charts": { + "peers_weight": "同伴权重", + "quorum_delta": "法定人数差", + "title": "法定人数图表", + "trended_weight": "趋势权重" + }, + "representatives_search": { + "placeholder": "按账户、别名、ip过滤" + }, + "representatives_weight": { + "trended": "趋势" + }, + "representatives_weight_chart": { + "title": "按代表的权重分布" + }, + "representatives_version_by_weight": { + "title": "版本" + }, + "roadmap": { + "header": { + "subtitle": "社区目标", + "title": "规划" + }, + "seo": { + "description": "Nano发展与社区路线图", + "tags": [ + "路线图", + "nano", + "未来", + "发布", + "设计", + "任务", + "讨论", + "社区", + "大使", + "管理者" + ], + "title": "路线图" + } + }, + "search_bar": { + "placeholder": "按地址/区块哈希搜索" + }, + "uptime": { + "now": "现在", + "days_ago": "天前" + } +} diff --git a/package.json b/package.json index 18cb527f..5dc73212 100644 --- a/package.json +++ b/package.json @@ -95,9 +95,12 @@ "express-favicon": "^2.0.4", "express-jwt": "^8.4.1", "express-robots-txt": "^1.0.0", + "express-slow-down": "^2.0.1", "fetch-cheerio-object": "^1.3.0", "front-matter": "^4.0.2", "fs-extra": "^11.1.1", + "i18next": "^23.8.2", + "i18next-http-backend": "^2.4.3", "jsonwebtoken": "^9.0.1", "knex": "^0.95.15", "markdown-it": "^12.3.2", @@ -116,6 +119,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-helmet": "^6.1.0", + "react-i18next": "^14.0.5", "react-redux": "^7.2.9", "react-router": "^5.3.4", "redux-saga": "^1.2.3", @@ -144,6 +148,7 @@ "compression-webpack-plugin": "^10.0.0", "concurrently": "^8.2.0", "copy-text-to-clipboard": "^3.2.0", + "copy-webpack-plugin": "^12.0.2", "cross-env": "^7.0.3", "css-loader": "6.8.1", "deepmerge": "4.3.1", diff --git a/src/core/api/service.js b/src/core/api/service.js index 05413f6b..f36328c5 100644 --- a/src/core/api/service.js +++ b/src/core/api/service.js @@ -32,9 +32,14 @@ export const api = { const url = `${API_URL}/posts/${id}?${queryString.stringify(params)}` return { url } }, - getDoc({ id }) { - const url = `${API_URL}/docs${id}.md` - return { url } + getDoc({ id, locale = 'en' }) { + if (locale === 'en') { + const url = `${API_URL}/docs${id}.md` + return { url } + } else { + const url = `${API_URL}/docs/${locale}${id}.md` + return { url } + } }, getLabelDoc({ id }) { const url = `${API_URL}/docs${id}.md` diff --git a/src/core/app/actions.js b/src/core/app/actions.js index e178832a..c671f3ee 100644 --- a/src/core/app/actions.js +++ b/src/core/app/actions.js @@ -1,11 +1,12 @@ export const appActions = { INIT_APP: 'INIT_APP', - init: ({ token, key }) => ({ + init: ({ token, key, locale }) => ({ type: appActions.INIT_APP, payload: { token, - key + key, + locale } }) } diff --git a/src/core/constants.js b/src/core/constants.js index c8b1dfb2..ca98ab23 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -12,3 +12,23 @@ export const WS_URL = IS_DEV ? 'ws://localhost:8080' : 'wss://nano.community' // 3 Million Nano (3e36) export const REP_MAX_WEIGHT = BigNumber(3).shiftedBy(36) +export const SUPPORTED_LOCALES = [ + 'ar', + 'en', + 'de', + 'es', + 'fa', + 'fr', + 'hi', + 'it', + 'ja', + 'ko', + 'nl', + 'pl', + 'pt', + 'ru', + 'tr', + 'vi', + 'zh', + 'no' +] diff --git a/src/core/docs/actions.js b/src/core/docs/actions.js index 2aa6f4d9..956cbcdb 100644 --- a/src/core/docs/actions.js +++ b/src/core/docs/actions.js @@ -19,10 +19,11 @@ export const docActions = { GET_LABEL_DOC_COMMIT_PENDING: 'GET_LABEL_DOC_COMMIT_PENDING', GET_LABEL_DOC_COMMIT_FULFILLED: 'GET_LABEL_DOC_COMMIT_FULFILLED', - getDoc: (id) => ({ + getDoc: ({ id, locale = 'en' }) => ({ type: docActions.GET_DOC, payload: { - id + id, + locale } }), diff --git a/src/core/docs/selectors.js b/src/core/docs/selectors.js index 903e7fdd..81cb2d57 100644 --- a/src/core/docs/selectors.js +++ b/src/core/docs/selectors.js @@ -1,11 +1,18 @@ import { Doc } from './doc' +import i18n from '@core/i18n' + export function getDocs(state) { return state.get('docs') } export function getDocById(state, { location }) { + const locale = i18n.language + const path = location.pathname - const id = path.endsWith('/') ? path.slice(0, -1) : path + let id = path.endsWith('/') ? path.slice(0, -1) : path + if (locale) { + id = id.replace(`/${locale}`, '') + } return getDocs(state).get(id, new Doc()) } diff --git a/src/core/i18n/actions.js b/src/core/i18n/actions.js new file mode 100644 index 00000000..4c999799 --- /dev/null +++ b/src/core/i18n/actions.js @@ -0,0 +1,11 @@ +export const i18nActions = { + CHANGE_LOCALE: 'CHANGE_LOCALE', + + change_locale: ({ locale, save }) => ({ + type: i18nActions.CHANGE_LOCALE, + payload: { + locale, + save + } + }) +} diff --git a/src/core/i18n/index.js b/src/core/i18n/index.js new file mode 100644 index 00000000..3fe3721d --- /dev/null +++ b/src/core/i18n/index.js @@ -0,0 +1,26 @@ +import { initReactI18next } from 'react-i18next' +import i18n from 'i18next' +import HttpBackend from 'i18next-http-backend' + +import { SUPPORTED_LOCALES } from '@core/constants' + +export { i18nActions } from './actions' +export { i18nReducer } from './reducer' +export { i18nSagas } from './sagas' + +i18n + .use(HttpBackend) + .use(initReactI18next) + .init({ + // detection + debug: true, + backend: { + // Configuration options for the backend plugin + loadPath: '/locales/{{lng}}.json' // Path to the translation files + }, + lng: 'en', + fallbackLng: 'en', + supportedLngs: SUPPORTED_LOCALES + }) + +export default i18n diff --git a/src/core/i18n/reducer.js b/src/core/i18n/reducer.js new file mode 100644 index 00000000..1891169f --- /dev/null +++ b/src/core/i18n/reducer.js @@ -0,0 +1,17 @@ +import { Record } from 'immutable' + +import { i18nActions } from './actions' + +const initialState = new Record({ + locale: 'en' +}) + +export function i18nReducer(state = initialState(), { payload, type }) { + switch (type) { + case i18nActions.CHANGE_LOCALE: + return state.set('locale', payload.locale) + + default: + return state + } +} diff --git a/src/core/i18n/sagas.js b/src/core/i18n/sagas.js new file mode 100644 index 00000000..cb6c0155 --- /dev/null +++ b/src/core/i18n/sagas.js @@ -0,0 +1,55 @@ +import { takeLatest, put, fork } from 'redux-saga/effects' +import i18n from 'i18next' + +import { localStorageAdapter } from '@core/utils' +import { appActions } from '@core/app/actions' +import { SUPPORTED_LOCALES } from '@core/constants' +import { i18nActions } from './actions' + +export function* init({ payload }) { + if (payload.locale) { + yield put( + i18nActions.change_locale({ locale: payload.locale, save: false }) + ) + } + + console.log('No locale saved') + + // detect user locale + const user_locale = navigator.language || navigator.languages[0] + + if (user_locale) { + const user_locale_key = user_locale.split('-')[0] + if (SUPPORTED_LOCALES.includes(user_locale_key)) { + console.log(`Setting locale to browser preference: ${user_locale_key}`) + yield put( + i18nActions.change_locale({ locale: user_locale_key, save: false }) + ) + } + } +} + +export function ChangeLocale({ payload }) { + if (payload.save) { + localStorageAdapter.setItem('locale', payload.locale) + } + i18n.changeLanguage(payload.locale) +} + +//= ==================================== +// WATCHERS +// ------------------------------------- + +export function* watchInitApp() { + yield takeLatest(appActions.INIT_APP, init) +} + +export function* watchChangeLocale() { + yield takeLatest(i18nActions.CHANGE_LOCALE, ChangeLocale) +} + +//= ==================================== +// ROOT +// ------------------------------------- + +export const i18nSagas = [fork(watchInitApp), fork(watchChangeLocale)] diff --git a/src/core/reducers.js b/src/core/reducers.js index e85abb34..7ee19b01 100644 --- a/src/core/reducers.js +++ b/src/core/reducers.js @@ -15,6 +15,7 @@ import { postsReducer } from './posts' import { postlistsReducer } from './postlists' import { nanodb_reducer } from './nanodb' import { api_reducer } from './api' +import { i18nReducer } from './i18n' const rootReducer = (history) => combineReducers({ @@ -32,7 +33,8 @@ const rootReducer = (history) => posts: postsReducer, postlists: postlistsReducer, nanodb: nanodb_reducer, - api: api_reducer + api: api_reducer, + i18n: i18nReducer }) export default rootReducer diff --git a/src/core/sagas.js b/src/core/sagas.js index b121138b..3938c284 100644 --- a/src/core/sagas.js +++ b/src/core/sagas.js @@ -11,6 +11,7 @@ import { ledgerSagas } from './ledger' import { networkSagas } from './network' import { postlistSagas } from './postlists' import { nanodb_sagas } from './nanodb' +import { i18nSagas } from './i18n' export default function* rootSage() { yield all([ @@ -24,6 +25,7 @@ export default function* rootSage() { ...ledgerSagas, ...networkSagas, ...postlistSagas, - ...nanodb_sagas + ...nanodb_sagas, + ...i18nSagas ]) } diff --git a/src/core/utils/local-storage.js b/src/core/utils/local-storage.js index b5120a79..a75b6a0c 100644 --- a/src/core/utils/local-storage.js +++ b/src/core/utils/local-storage.js @@ -1,11 +1,15 @@ /* global localStorage */ +const LOCAL_STORAGE_PREFIX = '/nano.community/' + export const localStorageAdapter = { getItem(key) { // return promise to match AsyncStorage usage on mobile return new Promise((resolve, reject) => { try { - const d = JSON.parse(localStorage.getItem(key)) + const d = JSON.parse( + localStorage.getItem(`${LOCAL_STORAGE_PREFIX}${key}`) + ) resolve(d) } catch (e) { reject(e) @@ -14,10 +18,10 @@ export const localStorageAdapter = { }, removeItem(key) { - localStorage.removeItem(key) + localStorage.removeItem(`${LOCAL_STORAGE_PREFIX}${key}`) }, setItem(key, value) { - localStorage.setItem(key, JSON.stringify(value)) + localStorage.setItem(`${LOCAL_STORAGE_PREFIX}${key}`, JSON.stringify(value)) } } diff --git a/src/styles/variables.styl b/src/styles/variables.styl index 39968701..a6248ee6 100644 --- a/src/styles/variables.styl +++ b/src/styles/variables.styl @@ -9,3 +9,6 @@ $nanoBlueGrey = #676686 $nanoLightBlue = #F4FAFF $hoverShadow = $borderColor + +$hoverBackground = rgba(255, 255, 255, 0.8) +$hoverBorder = rgba(0, 0, 0, 0.23) \ No newline at end of file diff --git a/src/views/components/account-blocks-summary/account-blocks-summary.js b/src/views/components/account-blocks-summary/account-blocks-summary.js index 1490080d..bab7eef0 100644 --- a/src/views/components/account-blocks-summary/account-blocks-summary.js +++ b/src/views/components/account-blocks-summary/account-blocks-summary.js @@ -11,103 +11,121 @@ import TableRow from '@mui/material/TableRow' import LinearProgress from '@mui/material/LinearProgress' import { Link } from 'react-router-dom' import dayjs from 'dayjs' +import { useTranslation } from 'react-i18next' import './account-blocks-summary.styl' -export default class AccountBlocksSummary extends React.Component { - render() { - const { account, type, accountLabel } = this.props +export default function AccountBlocksSummary({ account, type, accountLabel }) { + const { t } = useTranslation() + const items = account.getIn(['blocks_summary', type], []) + const isChange = type === 'change' - const items = account.getIn(['blocks_summary', type], []) - const isChange = type === 'change' + const is_loading = account.get( + `account_is_loading_blocks_${type}_summary`, + true + ) - const is_loading = account.get( - `account_is_loading_blocks_${type}_summary`, - true - ) - - return ( -
- - {is_loading && } - - + return ( +
+ + {is_loading && } +
+ + + + {t( + `accountBlocksSummary.${accountLabel.toLowerCase()}_account`, + `${accountLabel} Account` + )} + + + {t('account_blocks_summary.transactions', 'TXs')} + + {!isChange && ( + <> + + {t('common.total', 'Total')} + + + {t('account_blocks_summary.max_amount', 'Max Amount')} + + + {t('account_blocks_summary.min_amount', 'Min Amount')} + + + )} + + {t('account_blocks_summary.first_timestamp', 'First Timestamp')} + + + {t('account_blocks_summary.last_timestamp', 'Last Timestamp')} + + + + + {is_loading && ( + + Loading... + + )} + {!items.length && !is_loading && ( - {accountLabel} Account - TXs + No Records + + )} + {items.map((row) => ( + + + + {row.destination_alias || + `${row.destination_account.slice(0, 15)}...`} + + + + {BigNumber(row.block_count).toFormat(0)} + {!isChange && ( <> - Total - Max Amount - Min Amount + + {BigNumber(row.total_amount).shiftedBy(-30).toFormat()} + + + {BigNumber(row.max_amount).shiftedBy(-30).toFormat()} + + + {BigNumber(row.min_amount).shiftedBy(-30).toFormat()} + )} - First Timestamp - Last Timestamp + + {row.first_timestamp + ? dayjs(row.first_timestamp * 1000).format( + 'YYYY-MM-DD h:mm a' + ) + : '-'} + + + {row.last_timestamp + ? dayjs(row.last_timestamp * 1000).format( + 'YYYY-MM-DD h:mm a' + ) + : '-'} + - - - {is_loading && ( - - Loading... - - )} - {!items.length && !is_loading && ( - - No Records - - )} - {items.map((row) => ( - - - - {row.destination_alias || - `${row.destination_account.slice(0, 15)}...`} - - - - {BigNumber(row.block_count).toFormat(0)} - - {!isChange && ( - <> - - {BigNumber(row.total_amount).shiftedBy(-30).toFormat()} - - - {BigNumber(row.max_amount).shiftedBy(-30).toFormat()} - - - {BigNumber(row.min_amount).shiftedBy(-30).toFormat()} - - - )} - - {row.first_timestamp - ? dayjs(row.first_timestamp * 1000).format( - 'YYYY-MM-DD h:mm a' - ) - : '-'} - - - {row.last_timestamp - ? dayjs(row.last_timestamp * 1000).format( - 'YYYY-MM-DD h:mm a' - ) - : '-'} - - - ))} - -
- {items.length === 10 && ( -
- Showing top 10 accounts by total descending -
- )} -
-
- ) - } + ))} + + + {items.length === 10 && ( +
+ {t( + 'account_blocks_summary.showing_top_10', + 'Showing top 10 accounts by total descending' + )} +
+ )} + + + ) } AccountBlocksSummary.propTypes = { diff --git a/src/views/components/account-meta/account-meta.js b/src/views/components/account-meta/account-meta.js index 8fd10fdb..6f609c99 100644 --- a/src/views/components/account-meta/account-meta.js +++ b/src/views/components/account-meta/account-meta.js @@ -3,99 +3,97 @@ import ImmutablePropTypes from 'react-immutable-proptypes' import dayjs from 'dayjs' import { Link } from 'react-router-dom' import BigNumber from 'bignumber.js' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' -export default class AccountMeta extends React.Component { - render() { - const { account } = this.props +export default function AccountMeta({ account }) { + const { t } = useTranslation() + const funding_account = account.getIn(['open', 'funding_account'], '') + const funding_timestamp = account.getIn(['open', 'funding_timestamp']) + const open_timestamp = account.getIn(['open', 'open_timestamp']) + const open_balance = account.getIn(['open', 'open_balance']) + const pending_balance = account.getIn(['account_meta', 'pending']) + const height = account.getIn(['account_meta', 'confirmation_height']) + const modified_timestamp = account.getIn([ + 'account_meta', + 'modified_timestamp' + ]) + const items = [ + { + label: t('account_meta.funding_account', 'Funding Account'), + value: funding_account ? ( + + {account.getIn(['open', 'funding_alias']) || + `${funding_account.slice(0, 15)}...`} + + ) : ( + '-' + ) + }, + { + label: t('account_meta.funding_timestamp', 'Funding Timestamp'), + value: funding_timestamp + ? `${dayjs(funding_timestamp * 1000).format( + 'MMM D, YYYY h:mm a' + )} (${timeago.format(funding_timestamp * 1000, 'nano_short')} ago)` + : '-' + }, + { + label: t('account_meta.open_timestamp', 'Open Timestamp'), + value: open_timestamp + ? `${dayjs(open_timestamp * 1000).format( + 'MMM D, YYYY h:mm a' + )} (${timeago.format(open_timestamp * 1000, 'nano_short')} ago)` + : '-' + }, + { + label: t('account_meta.opening_balance', 'Opening Balance'), + value: open_balance + ? BigNumber(open_balance).shiftedBy(-30).toFormat() + : '-' + }, + { + label: t('account_meta.receivable_balance', 'Receivable Balance'), + value: pending_balance + ? BigNumber(pending_balance).shiftedBy(-30).toFormat() + : '-' + }, + { + label: t('common.version', 'Version'), + value: account.getIn(['account_meta', 'account_version'], '-') + }, + { + label: t('account_meta.height', 'Height'), + value: height ? BigNumber(height).toFormat() : '-' + }, + { + label: t('account_meta.last_modified', 'Last Modified'), + value: modified_timestamp + ? `${dayjs(modified_timestamp * 1000).format( + 'MMM D, YYYY h:mm a' + )} (${timeago.format(modified_timestamp * 1000, 'nano_short')} ago)` + : '-' + } + ] - const fundingAccount = account.getIn(['open', 'funding_account'], '') - const fundingTimestamp = account.getIn(['open', 'funding_timestamp']) - const openTimestamp = account.getIn(['open', 'open_timestamp']) - const openBalance = account.getIn(['open', 'open_balance']) - const pendingBalance = account.getIn(['account_meta', 'pending']) - const height = account.getIn(['account_meta', 'confirmation_height']) - const modifiedTimestamp = account.getIn([ - 'account_meta', - 'modified_timestamp' - ]) - const items = [ - { - label: 'Funding Account', - value: fundingAccount ? ( - - {account.getIn(['open', 'funding_alias']) || - `${fundingAccount.slice(0, 15)}...`} - - ) : ( - '-' - ) - }, - { - label: 'Funding Timestamp', - value: fundingTimestamp - ? `${dayjs(fundingTimestamp * 1000).format( - 'MMM D, YYYY h:mm a' - )} (${timeago.format(fundingTimestamp * 1000, 'nano_short')} ago)` - : '-' - }, - { - label: 'Open Timestamp', - value: openTimestamp - ? `${dayjs(openTimestamp * 1000).format( - 'MMM D, YYYY h:mm a' - )} (${timeago.format(openTimestamp * 1000, 'nano_short')} ago)` - : '-' - }, - { - label: 'Opening Balance', - value: openBalance - ? BigNumber(openBalance).shiftedBy(-30).toFormat() - : '-' - }, - { - label: 'Receivable Balance', - value: pendingBalance - ? BigNumber(pendingBalance).shiftedBy(-30).toFormat() - : '-' - }, - { - label: 'Version', - value: account.getIn(['account_meta', 'account_version'], '-') - }, - { - label: 'Height', - value: height ? BigNumber(height).toFormat() : '-' - }, - { - label: 'Last Modified', - value: modifiedTimestamp - ? `${dayjs(modifiedTimestamp * 1000).format( - 'MMM D, YYYY h:mm a' - )} (${timeago.format(modifiedTimestamp * 1000, 'nano_short')} ago)` - : '-' - } - ] + const rows = items.map((item, idx) => ( +
+
{item.label}
+
{item.value}
+
+ )) - const rows = items.map((i, idx) => ( -
-
{i.label}
-
{i.value}
-
- )) - - return ( -
-
-
- Account Info -
- {rows} + return ( +
+
+
+ {t('account_meta.account_info', 'Account Info')}
+ {rows}
- ) - } +
+ ) } AccountMeta.propTypes = { diff --git a/src/views/components/app/app.js b/src/views/components/app/app.js index 1306392f..78bf4c07 100644 --- a/src/views/components/app/app.js +++ b/src/views/components/app/app.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { Suspense } from 'react' import PropTypes from 'prop-types' import { localStorageAdapter } from '@core/utils' @@ -16,7 +16,8 @@ export default class App extends React.Component { async componentDidMount() { const token = await localStorageAdapter.getItem('token') const key = await localStorageAdapter.getItem('key') - this.props.init({ token, key }) + const locale = await localStorageAdapter.getItem('locale') + this.props.init({ token, key, locale }) this.props.getRepresentatives() this.props.getNetworkStats() this.props.getGithubEvents() @@ -24,11 +25,12 @@ export default class App extends React.Component { } render() { + // TODO improve loading UX return ( - <> + }> - + ) } } diff --git a/src/views/components/block-info/block-info.js b/src/views/components/block-info/block-info.js index 0578ab6e..550c45ae 100644 --- a/src/views/components/block-info/block-info.js +++ b/src/views/components/block-info/block-info.js @@ -5,27 +5,45 @@ import dayjs from 'dayjs' import { Link } from 'react-router-dom' import LoopIcon from '@mui/icons-material/Loop' import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' import './block-info.styl' function BlockType({ type }) { + const { t } = useTranslation() switch (type) { case 'epoch': - return
Epoch
+ return ( +
+ {t('block_type.epoch', 'Epoch')} +
+ ) case 'send': - return
Send
+ return ( +
{t('block_type.send', 'Send')}
+ ) case 'receive': - return
Receive
+ return ( +
+ {t('block_type.receive', 'Receive')} +
+ ) case 'change': - return
Change
+ return ( +
+ {t('block_type.change', 'Change')} +
+ ) case 'open': - return
Open
+ return ( +
{t('block_type.open', 'Open')}
+ ) } } @@ -34,11 +52,12 @@ BlockType.propTypes = { } function BlockStatus({ confirmed }) { + const { t } = useTranslation() if (confirmed) { return (
- Confirmed + {t('block_status.confirmed', 'Confirmed')}
) } @@ -46,7 +65,7 @@ function BlockStatus({ confirmed }) { return (
- Unconfirmed + {t('block_status.unconfirmed', 'Unconfirmed')}
) } @@ -55,54 +74,50 @@ BlockStatus.propTypes = { confirmed: PropTypes.bool } -export default class BlockInfo extends React.Component { - render() { - const { block, type } = this.props - - const timestamp = parseInt( - block.getIn(['blockInfo', 'local_timestamp'], 0), - 10 - ) - // const previous = block.getIn(['blockInfo', 'contents', 'previous']) - const isConfirmed = block.blockInfo.confirmed === 'true' - - const items = [ - { - label: 'Status', - value: - }, - { - label: 'Operation', - value: - }, - { - label: 'Timestamp', - value: timestamp - ? `${dayjs(timestamp * 1000).format( - 'MMM D, YYYY h:mm a' - )} (${timeago.format(timestamp * 1000, 'nano_short')} ago)` - : '-' - }, - { - label: 'Block Account', - value: ( - - {block.blockAccountAlias || - `${block.blockInfo.block_account.slice(0, 15)}...`} - - ) - } - ] - - const rows = items.map((i, idx) => ( -
-
{i.label}
-
{i.value}
-
- )) +export default function BlockInfo({ block, type }) { + const { t } = useTranslation() + const timestamp = parseInt( + block.getIn(['blockInfo', 'local_timestamp'], 0), + 10 + ) + const isConfirmed = block.blockInfo.confirmed === 'true' + + const items = [ + { + label: t('block_info.status', 'Status'), + value: + }, + { + label: t('block_info.operation', 'Operation'), + value: + }, + { + label: t('block_info.timestamp', 'Timestamp'), + value: timestamp + ? `${dayjs(timestamp * 1000).format( + 'MMM D, YYYY h:mm a' + )} (${timeago.format(timestamp * 1000, 'nano_short')} ago)` + : '-' + }, + { + label: t('block_info.block_account', 'Block Account'), + value: ( + + {block.blockAccountAlias || + `${block.blockInfo.block_account.slice(0, 15)}...`} + + ) + } + ] + + const rows = items.map((i, idx) => ( +
+
{i.label}
+
{i.value}
+
+ )) - return
{rows}
- } + return
{rows}
} BlockInfo.propTypes = { diff --git a/src/views/components/change-locale/change-locale.js b/src/views/components/change-locale/change-locale.js new file mode 100644 index 00000000..a0be7939 --- /dev/null +++ b/src/views/components/change-locale/change-locale.js @@ -0,0 +1,73 @@ +import React from 'react' +import PropTypes from 'prop-types' +import FormControl from '@mui/material/FormControl' +import Select from '@mui/material/Select' +import MenuItem from '@mui/material/MenuItem' +import SvgIcon from '@mui/material/SvgIcon' + +import './change-locale.styl' + +function TranslateIcon(props) { + return ( + + + + + ) +} + +export default function ChangeLocale({ change_locale, locale }) { + const locale_texts = { + ar: 'العربية', + en: 'English', + es: 'Español', + fa: 'فارسی', + fr: 'Français', + hi: 'हिन्दी', + it: 'Italiano', + ja: '日本語', + de: 'Deutsch', + nl: 'Nederlands', + ru: 'Русский', + ko: '한국어', + pl: 'Polski', + pt: 'Português', + tr: 'Türkçe', + vi: 'Tiếng Việt', + zh: '中文', + no: 'Norsk' + } + + return ( + + + + ) +} + +ChangeLocale.propTypes = { + change_locale: PropTypes.func.isRequired, + locale: PropTypes.string.isRequired +} diff --git a/src/views/components/change-locale/change-locale.styl b/src/views/components/change-locale/change-locale.styl new file mode 100644 index 00000000..774adf01 --- /dev/null +++ b/src/views/components/change-locale/change-locale.styl @@ -0,0 +1,15 @@ +.change-locale.MuiFormControl-root + margin 0 auto + max-width 160px + margin 8px + + .MuiOutlinedInput-notchedOutline + border-color lighten($borderColor, 40%) + + &:hover + .MuiInputBase-root + background $hoverBackground + + .MuiOutlinedInput-notchedOutline + border-color $hoverBorder + box-shadow $hoverShadow 4px 4px 0px 0px diff --git a/src/views/components/change-locale/index.js b/src/views/components/change-locale/index.js new file mode 100644 index 00000000..5d78615d --- /dev/null +++ b/src/views/components/change-locale/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux' +import { createSelector } from 'reselect' + +import { i18nActions } from '@core/i18n' + +import ChangeLocale from './change-locale' + +const mapStateToProps = createSelector( + (state) => state.getIn(['i18n', 'locale']), + (locale) => ({ locale }) +) + +const mapDispatchToProps = { + change_locale: i18nActions.change_locale +} + +export default connect(mapStateToProps, mapDispatchToProps)(ChangeLocale) diff --git a/src/views/components/github-events/github-events.js b/src/views/components/github-events/github-events.js index 1920b737..4c336e03 100644 --- a/src/views/components/github-events/github-events.js +++ b/src/views/components/github-events/github-events.js @@ -1,57 +1,92 @@ import React from 'react' +import PropTypes from 'prop-types' import ImmutablePropTypes from 'react-immutable-proptypes' import Skeleton from '@mui/material/Skeleton' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' import './github-events.styl' -const action = (item) => { +const action = ({ item, t }) => { switch (item.type) { case 'CommitCommentEvent': - return 'commented on commit' + return t( + 'github_events.action.commented_on_commit', + 'commented on commit' + ) case 'CreateEvent': - return `created ${item.action}` + return t( + 'github_events.action.created', + { action: item.action }, + `created ${item.action}` + ) case 'DeleteEvent': - return `deleted ${item.action}` + return t( + 'github_events.action.deleted', + { action: item.action }, + `deleted ${item.action}` + ) case 'ForkEvent': - return 'forked' + return t('github_events.action.forked', 'forked') case 'IssueCommentEvent': - return 'commented on issue' + return t('github_events.action.commented_on_issue', 'commented on issue') case 'IssuesEvent': - return `${item.action} issue` + return t( + 'github_events.action.issue_action', + { action: item.action }, + `${item.action} issue` + ) case 'PublicEvent': - return 'made public' + return t('github_events.action.made_public', 'made public') case 'MemberEvent': - return 'added member' + return t('github_events.action.added_member', 'added member') case 'SponsorshipEvent': - return 'sponshorship started' + return t( + 'github_events.action.sponsorship_started', + 'sponsorship started' + ) case 'PullRequestEvent': - return `${item.action} pr` + return t( + 'github_events.action.pr_action', + { action: item.action }, + `${item.action} pr` + ) case 'PullRequestReviewEvent': - return `pr review ${item.title}` + return t( + 'github_events.action.pr_review', + { title: item.title }, + `pr review ${item.title}` + ) case 'PullRequestReviewCommentEvent': - return 'commented on pr review' + return t( + 'github_events.action.commented_on_pr_review', + 'commented on pr review' + ) case 'PushEvent': - return `pushed commit to ${item.ref.slice(0, 15)}` + return t( + 'github_events.action.pushed_commit', + { ref: item.ref.slice(0, 15) }, + `pushed commit to ${item.ref.slice(0, 15)}` + ) case 'ReleaseEvent': - return 'published release' + return t('github_events.action.published_release', 'published release') case 'WatchEvent': - return 'watching repo' + return t('github_events.action.watching_repo', 'watching repo') } } @@ -71,11 +106,11 @@ const link = (item) => { } } -const GithubEvent = (item, index) => { +const GithubEvent = ({ item, index, t }) => { return (
{item.actor_name}
-
{action(item)}
+
{action({ item, t })}
{item.event_url && ( {link(item)} @@ -88,27 +123,34 @@ const GithubEvent = (item, index) => { ) } -export default class GithubEvents extends React.Component { - render() { - const { events } = this.props - const items = events.map((i, idx) => GithubEvent(i, idx)) - const skeletons = new Array(15).fill(undefined) - - return ( -
-
Development Events
-
- {Boolean(items.size) && items} - {!items.size && - skeletons.map((i, idx) => ( -
- -
- ))} -
+GithubEvent.propTypes = { + item: ImmutablePropTypes.record, + index: ImmutablePropTypes.number, + t: PropTypes.func +} + +export default function GithubEvents({ events }) { + const { t } = useTranslation() + + const items = events.map((item, index) => GithubEvent({ item, index, t })) + const skeletons = new Array(15).fill(undefined) + + return ( +
+
+ {t('github_events.events_title', 'Development Events')}
- ) - } +
+ {Boolean(items.size) && items} + {!items.size && + skeletons.map((i, idx) => ( +
+ +
+ ))} +
+
+ ) } GithubEvents.propTypes = { diff --git a/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js b/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js index 35bbee8d..c3a52758 100644 --- a/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js +++ b/src/views/components/ledger-chart-addresses/ledger-chart-addresses.js @@ -10,6 +10,7 @@ import { } from 'echarts/components' import { CanvasRenderer } from 'echarts/renderers' import Button from '@mui/material/Button' +import { useTranslation } from 'react-i18next' import { download_csv, download_json } from '@core/utils' import LedgerChartMetrics from '@components/ledger-chart-metrics' @@ -23,6 +24,7 @@ echarts.use([ ]) export default function LedgerChartAddresses({ data, isLoading }) { + const { t } = useTranslation() const option = { grid: { containLabel: true @@ -126,17 +128,20 @@ export default function LedgerChartAddresses({ data, isLoading }) {
- Description + {t('ledger.description', 'Description')}

- The total number of active, new, and reused addresses used per - day. + {t( + 'ledger.addresses.total_number', + 'The total number of active, new, and reused addresses used per day.' + )}

- Active shows the number of unique addresses used. New shows the - number of addresses created. Reused shows the number of addresses - used that were created on a previous day. + {t( + 'ledger.addresses.active_detail', + 'Active shows the number of unique addresses used. New shows the number of addresses created. Reused shows the number of addresses used that were created on a previous day.' + )}

{!isLoading && ( @@ -152,9 +157,12 @@ export default function LedgerChartAddresses({ data, isLoading }) {
+ -
) diff --git a/src/views/components/ledger-chart-amounts/ledger-chart-amounts.js b/src/views/components/ledger-chart-amounts/ledger-chart-amounts.js index 979ab297..bfbb0218 100644 --- a/src/views/components/ledger-chart-amounts/ledger-chart-amounts.js +++ b/src/views/components/ledger-chart-amounts/ledger-chart-amounts.js @@ -11,6 +11,7 @@ import { } from 'echarts/components' import { CanvasRenderer } from 'echarts/renderers' import Button from '@mui/material/Button' +import { useTranslation } from 'react-i18next' import { download_csv, download_json } from '@core/utils' @@ -48,6 +49,7 @@ const color_map = { } export default function LedgerChartAmounts({ data, isLoading }) { + const { t } = useTranslation() const ranges = { _1000000_count: '>1M', _100000_count: '100k to 1M', @@ -114,7 +116,8 @@ export default function LedgerChartAmounts({ data, isLoading }) { { type: 'log', min: 1, - max: 5000000 + max: 5000000, + name: t('common.blocks', 'Blocks') } ], series: series_data @@ -170,11 +173,13 @@ export default function LedgerChartAmounts({ data, isLoading }) {
- Description + {t('ledger.description', 'Description')}
- The number of confirmed send-type blocks per day where the amount in - the block is in a given range (in Nano) + {t( + 'ledger.amounts.total_number', + 'The number of confirmed send-type blocks per day where the amount in the block is in a given range (in Nano)' + )}
{!isLoading && (
diff --git a/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js b/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js index b56fd5c2..92190c6a 100644 --- a/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js +++ b/src/views/components/ledger-chart-blocks/ledger-chart-blocks.js @@ -10,6 +10,7 @@ import { GridComponent } from 'echarts/components' import { CanvasRenderer } from 'echarts/renderers' +import { useTranslation } from 'react-i18next' import LedgerChartMetrics from '@components/ledger-chart-metrics' import { download_csv, download_json } from '@core/utils' @@ -23,6 +24,7 @@ echarts.use([ ]) export default function LedgerChartBlocks({ data, isLoading }) { + const { t } = useTranslation() const option = { grid: { containLabel: true @@ -40,13 +42,13 @@ export default function LedgerChartBlocks({ data, isLoading }) { }, yAxis: { type: 'log', - name: 'Blocks', + name: t('common.blocks', 'Blocks'), min: 1 }, series: [ { type: 'line', - name: 'Total', + name: t('common.Total', 'Total'), showSymbol: false, lineStyle: { width: 1 @@ -55,7 +57,7 @@ export default function LedgerChartBlocks({ data, isLoading }) { }, { type: 'line', - name: 'Send', + name: t('block_type.send', 'Send'), showSymbol: false, lineStyle: { width: 1 @@ -64,7 +66,7 @@ export default function LedgerChartBlocks({ data, isLoading }) { }, { type: 'line', - name: 'Change', + name: t('block_type.change', 'Change'), showSymbol: false, lineStyle: { width: 1 @@ -73,7 +75,7 @@ export default function LedgerChartBlocks({ data, isLoading }) { }, { type: 'line', - name: 'Receive', + name: t('block_type.receive', 'Receive'), showSymbol: false, lineStyle: { width: 1 @@ -82,7 +84,7 @@ export default function LedgerChartBlocks({ data, isLoading }) { }, { type: 'line', - name: 'Open', + name: t('block_type.open', 'Open'), showSymbol: false, lineStyle: { width: 1 @@ -148,10 +150,13 @@ export default function LedgerChartBlocks({ data, isLoading }) {
- Description + {t('ledger.description', 'Description')}
- The number of confirmed blocks (by type) per day. + {t( + 'ledger.blocks.description', + 'The number of blocks confirmed per day.' + )}
{!isLoading && (
@@ -166,27 +171,27 @@ export default function LedgerChartBlocks({ data, isLoading }) {
diff --git a/src/views/components/ledger-chart-metrics/ledger-chart-metrics.js b/src/views/components/ledger-chart-metrics/ledger-chart-metrics.js index 6f4b843a..ed528262 100644 --- a/src/views/components/ledger-chart-metrics/ledger-chart-metrics.js +++ b/src/views/components/ledger-chart-metrics/ledger-chart-metrics.js @@ -2,6 +2,7 @@ import React from 'react' import dayjs from 'dayjs' import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' +import { useTranslation } from 'react-i18next' import './ledger-chart-metrics.styl' @@ -10,6 +11,7 @@ export default function LedgerChartMetrics({ label, show_total = false }) { + const { t } = useTranslation() const values = data.map((d) => d[1]) const max = values.length ? Math.max(...values) : null const min = values.length ? Math.min(...values.filter(Boolean)) : null @@ -28,7 +30,9 @@ export default function LedgerChartMetrics({
-
Min
+
+ {t('common.min', 'Min')} +
{min ? BigNumber(min).toFormat(0) : '-'}
@@ -37,7 +41,9 @@ export default function LedgerChartMetrics({
-
Max
+
+ {t('common.max', 'Max')} +
{max ? BigNumber(max).toFormat(0) : '-'}
@@ -47,7 +53,9 @@ export default function LedgerChartMetrics({
{show_total && (
-
Total
+
+ {t('common.total', 'Total')} +
{total ? BigNumber(total).toFormat(0) : '-'}
diff --git a/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js b/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js index 90e7e190..85ca0130 100644 --- a/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js +++ b/src/views/components/ledger-chart-usd-transferred/ledger-chart-usd-transferred.js @@ -11,6 +11,7 @@ import { } from 'echarts/components' import { CanvasRenderer } from 'echarts/renderers' import Button from '@mui/material/Button' +import { useTranslation } from 'react-i18next' import LedgerChartMetrics from '@components/ledger-chart-metrics' import { download_csv, download_json } from '@core/utils' @@ -24,6 +25,7 @@ echarts.use([ ]) export default function LedgerUSDTransferred({ data, isLoading }) { + const { t } = useTranslation() const span_style = 'float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900' @@ -81,7 +83,7 @@ export default function LedgerUSDTransferred({ data, isLoading }) { series: [ { type: 'line', - name: 'USD Transferred', + name: t('ledger.usd_transferred.usd_transferred', 'USD Transferred'), showSymbol: false, lineStyle: { width: 1 @@ -132,13 +134,20 @@ export default function LedgerUSDTransferred({ data, isLoading }) {
- Description + {t('ledger.description', 'Description')}
-

The total amount of value transferred (in USD) per day.

- Based on the daily closing price of Nano/USD and the total amount - of Nano transferred that day. + {t( + 'ledger.usd_transferred.desc_1', + 'The total amount of value transferred (in USD) per day.' + )} +

+

+ {t( + 'ledger.usd_transferred.desc_2', + 'Based on the daily closing price of Nano/USD and the total amount of Nano transferred that day.' + )}

{!isLoading && ( @@ -154,7 +163,10 @@ export default function LedgerUSDTransferred({ data, isLoading }) {
[d[0], d[1]])} - label='USD Transferred Stats' + label={t( + 'ledger.usd_transferred.usd_transferred_stats', + 'USD Transferred Stats' + )} show_total />
diff --git a/src/views/components/ledger-chart-volume/ledger-chart-volume.js b/src/views/components/ledger-chart-volume/ledger-chart-volume.js index 852ce9f4..2381c1cd 100644 --- a/src/views/components/ledger-chart-volume/ledger-chart-volume.js +++ b/src/views/components/ledger-chart-volume/ledger-chart-volume.js @@ -11,6 +11,7 @@ import { } from 'echarts/components' import { CanvasRenderer } from 'echarts/renderers' import Button from '@mui/material/Button' +import { useTranslation } from 'react-i18next' import LedgerChartMetrics from '@components/ledger-chart-metrics' import { download_csv, download_json } from '@core/utils' @@ -24,6 +25,7 @@ echarts.use([ ]) export default function LedgerChartVolume({ data, isLoading }) { + const { t } = useTranslation() const span_style = 'float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900' @@ -82,7 +84,7 @@ export default function LedgerChartVolume({ data, isLoading }) { series: [ { type: 'line', - name: 'Send', + name: t('block_type.send', 'Send'), showSymbol: false, lineStyle: { width: 1 @@ -91,7 +93,7 @@ export default function LedgerChartVolume({ data, isLoading }) { }, { type: 'line', - name: 'Change', + name: t('block_type.change', 'Change'), showSymbol: false, lineStyle: { width: 1 @@ -150,11 +152,13 @@ export default function LedgerChartVolume({ data, isLoading }) {
- Description + {t('ledger.description', 'Description')}
- The total amount sent (in Nano) and total amount of voting weight - changed per day. + {t( + 'ledger.volume.description', + 'The total amount sent (in Nano) and total amount of voting weight changed per day.' + )}
{!isLoading && (
@@ -169,12 +173,12 @@ export default function LedgerChartVolume({ data, isLoading }) {
diff --git a/src/views/components/menu/menu.js b/src/views/components/menu/menu.js index c76e36ea..0c91b3a9 100644 --- a/src/views/components/menu/menu.js +++ b/src/views/components/menu/menu.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { NavLink } from 'react-router-dom' import PropTypes from 'prop-types' import SwipeableDrawer from '@mui/material/SwipeableDrawer' @@ -6,183 +6,232 @@ import CloseIcon from '@mui/icons-material/Close' import SpeedDial from '@mui/material/SpeedDial' import SpeedDialAction from '@mui/material/SpeedDialAction' import HomeIcon from '@mui/icons-material/Home' +import { useTranslation } from 'react-i18next' import SearchBar from '@components/search-bar' import history from '@core/history' +import ChangeLocale from '@components/change-locale' import './menu.styl' const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) function MenuSections() { + const { t, i18n } = useTranslation() + const locale = i18n.language return (
-
Introduction
+
+ {t('menu.introduction', 'Introduction')} +
- Overview - Advantages - How it works - Why it matters - Misconceptions - - Investment thesis - - History - FAQs + + {t('menu.overview', 'Overview')} + + + {t('menu.advantages', 'Advantages')} + + + {t('menu.how_it_works', 'How it works')} + + + {t('menu.why_it_matters', 'Why it matters')} + + + {t('menu.misconceptions', 'Misconceptions')} + + + {t('menu.investment_thesis', 'Investment thesis')} + + + {t('menu.history', 'History')} + + {t('menu.faqs', 'FAQs')}
-
Guides
+
{t('menu.guides', 'Guides')}
- Basics - Storing - Acquiring - - Choosing a Rep + + {t('menu.basics', 'Basics')} + + + {t('menu.storing', 'Storing')} - Using - - Account Setup + + {t('menu.acquiring', 'Acquiring')} - Privacy - - Best Practices + + {t('menu.choosing_a_rep', 'Choosing a Rep')} + + + {t('menu.using', 'Using')} + + + {t('menu.account_setup', 'Account Setup')} + + + {t('menu.privacy', 'Privacy')} + + + {t('menu.best_practices', 'Best Practices')}
-
Learn
+
{t('menu.learn', 'Learn')}
- Design - Security - Attack Vectors - Challenges - Glossary - Get Support + + {t('menu.design', 'Design')} + + + {t('menu.security', 'Security')} + + + {t('menu.attack_vectors', 'Attack Vectors')} + + + {t('menu.challenges', 'Challenges')} + + + {t('menu.glossary', 'Glossary')} + + + {t('menu.get_support', 'Get Support')} +
-
Developers
+
+ {t('menu.developers', 'Developers')} +
- - Getting Started + + {t('menu.getting_started', 'Getting Started')} - - Integrations + + {t('menu.integrations', 'Integrations')} - - Running a node + + {t('menu.running_a_node', 'Running a node')} - {/* - Tutorials - */} - - Documentation + + {t('menu.documentation', 'Documentation')} - - Protocol + + {t('menu.protocol', 'Protocol')} - {/* Integrations */} - - Developer Discussions + + {t('menu.developer_discussions', 'Developer Discussions')}
-
Get Involved
+
+ {t('menu.get_involved', 'Get Involved')} +
- Planning 👾 - Contribution Guide - Communities + {t('menu.planning', 'Planning 👾')} + + {t('menu.contribution_guide', 'Contribution Guide')} + + + {t('menu.communities', 'Communities')} +
-
Stats
+
{t('menu.stats', 'Stats')}
- Representatives - Telemetry - Ledger + + {t('common.representative', { + count: 2, + defaultValue: 'Representatives' + })} + + {t('menu.telemetry', 'Telemetry')} + {t('menu.ledger', 'Ledger')}
-
Topics
+
{t('menu.topics', 'Topics')}
- Privacy + + {t('menu.privacy', 'Privacy')} +
) } -export default class Menu extends React.Component { - constructor(props) { - super(props) - this.state = { - open: false - } - } +export default function Menu({ hide, hideSearch, hide_speed_dial }) { + const [open, setOpen] = useState(false) + const { t } = useTranslation() - handleOpen = () => this.setState({ open: true }) - handleClose = () => this.setState({ open: false }) - handleClick = () => this.setState({ open: !this.state.open }) - handleHomeClick = () => history.push('/') + const handleOpen = () => setOpen(true) + const handleClose = () => setOpen(false) + const handleClick = () => setOpen(!open) + const handleHomeClick = () => history.push('/') - render() { - const { hide, hideSearch, hide_speed_dial } = this.props - const isHome = history.location.pathname === '/' - const isMobile = window.innerWidth < 750 + const isHome = history.location.pathname === '/' + const isMobile = window.innerWidth < 750 - return ( -
- - - - {!hide_speed_dial && ( - - } - openIcon={}> - {!isHome && ( - } - tooltipTitle='Home' - tooltipPlacement={isMobile ? 'left' : 'right'} - onClick={this.handleHomeClick} - /> - )} - - )} -
- {isHome ? ( -
NANO
- ) : ( - - NANO - - )} - {!hideSearch && } - {!hide && } + return ( +
+ + +
+
+
+ {!hide_speed_dial && ( + + } + openIcon={}> + {!isHome && ( + } + tooltipTitle={t('menu.home', 'Home')} + tooltipPlacement={isMobile ? 'left' : 'right'} + onClick={handleHomeClick} + /> + )} + + )} +
+ {isHome ? ( +
NANO
+ ) : ( + + NANO + + )} + {!hideSearch && } + {!hide && } + {!isHome && }
- ) - } +
+ ) } Menu.propTypes = { diff --git a/src/views/components/menu/menu.styl b/src/views/components/menu/menu.styl index 75471c56..c7f1ccfc 100644 --- a/src/views/components/menu/menu.styl +++ b/src/views/components/menu/menu.styl @@ -1,6 +1,3 @@ -$hoverBackground = rgba(255, 255, 255, 0.8) -$hoverBorder = rgba(0, 0, 0, 0.23) - .menu__dial position fixed left 16px @@ -46,10 +43,11 @@ $hoverBorder = rgba(0, 0, 0, 0.23) .MuiDrawer-paper.MuiPaper-root background $backgroundColor border-radius 0 0 32px 32px + padding 16px 32px .menu__sections + .settings__container max-width 1100px margin 0 auto - padding 16px 32px .menu__section padding 16px diff --git a/src/views/components/network/network.js b/src/views/components/network/network.js index 2409c93f..14d20432 100644 --- a/src/views/components/network/network.js +++ b/src/views/components/network/network.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import HelpOutlineIcon from '@mui/icons-material/HelpOutline' import Tooltip from '@mui/material/Tooltip' import ImmutablePropTypes from 'react-immutable-proptypes' +import { useTranslation } from 'react-i18next' import './network.styl' @@ -22,245 +23,256 @@ const convert_ms_to_readable_time = (ms) => { } } -export default class Network extends React.Component { - render() { - const { - network, - wattHour, - stats, - unconfirmed_block_pool_count, - send_volume_nano - } = this.props +export default function Network({ + network, + wattHour, + stats, + unconfirmed_block_pool_count, + send_volume_nano +}) { + const { t } = useTranslation() - const prText = - 'as observed across the networks principal representatives: voting nodes with more than 0.1% of the online voting weight delegated to them' + const confirmations_text = t( + 'network.confirmations_text', + 'Total number of transactions confirmed by the network over the last 24 hours' + ) + const settlement_text = t( + 'network.settlement_text', + 'Total amount of value settled by the network over the last 24 hours (only send blocks)' + ) + const throughput_text = t( + 'network.throughput_text', + 'Median number of transactions confirmed per second in the last minute $t(network.pr_text)' + ) + const speed_text = t( + 'network.speed_text', + 'Time in milliseconds for a test transaction to get confirmed' + ) + const unconfirmed_pool_text = t( + 'network.unconfirmed_pool_text', + 'Median number of transactions waiting to be confirmed $t(network.pr_text)' + ) + const stake_text = t( + 'network.stake_text', + 'Percentage of delegated Nano weight actively participating in voting' + ) + const confirm_text = t( + 'network.confirm_text', + 'The minimum number of representatives needed to confirm transactions' + ) + const censor_text = t( + 'network.censor_text', + 'The minimum number of representatives needed to censor transactions or stall the network' + ) + const fee_text = t( + 'network.fee_text', + 'The Nano network operates without fees' + ) + const energy_text = t( + 'network.energy_text', + 'Estimated live network CPU energy usage of Principle Representatives based on collected CPU model info. The estimate is based on CPU TDP, which is the average power, in watts, the processor dissipates when operating at base frequency with all cores active under manufacture-defined, high-complexity workload' + ) - const confirmationsText = - 'Total number of transactions confirmed by the network over the last 24 hours' - const settlementText = - 'Total amount of value settled by the network over the last 24 hours (only send blocks)' - const throughputText = `Median number of transactions confirmed per second in the last minute ${prText}` - const speedText = - 'Median time in milliseconds for a block to get confirmed (across all buckets)' - const unconfirmed_pool_text = `Number of blocks waiting to be confirmed ${prText}` - const stakeText = - 'Percentage of delegated Nano weight actively participating in voting' - const confirmText = - 'The minimum number of representatives needed to confirm transactions' - const censorText = - 'The minimum number of representatives needed to censor transactions or stall the network' - const feeText = 'The Nano network operates without fees' - const energyText = - 'Estimated live network CPU energy usage of Principle Representatives based on collected CPU model info. The estimate is based on CPU TDP, which is the average power, in watts, the processor dissipates when operating at base frequency with all cores active under manufacture-defined, high-complexity workload' - - return ( -
-
Network Stats
-
-
- Confirmations (24h) - - - -
-
- {network.getIn(['stats', 'nanodb', 'confirmations_last_24_hours']) - ? format_number( - network.getIn([ - 'stats', - 'nanodb', - 'confirmations_last_24_hours' - ]) - ) - : '-'} -
+ return ( +
+
+ {t('network.stats_title', 'Network Stats')} +
+
+
+ {t('network.confirmations', 'Confirmations (24h)')} + + + +
+
+ {network.getIn(['stats', 'nanodb', 'confirmations_last_24_hours']) + ? format_number( + network.getIn([ + 'stats', + 'nanodb', + 'confirmations_last_24_hours' + ]) + ) + : '-'} +
+
+
+
+ {t('network.settlement', 'Settlement (24h)')} + + +
-
-
- Settlement (24h) - - - -
-
- {network.getIn(['stats', 'current_price_usd']) - ? `$${format_number( - ( - send_volume_nano * - network.getIn(['stats', 'current_price_usd']) - ).toFixed(0) - )}` - : '-'} -
+
+ {network.getIn(['stats', 'current_price_usd']) + ? `$${format_number( + ( + send_volume_nano * + network.getIn(['stats', 'current_price_usd']) + ).toFixed(0) + )}` + : '-'}
-
-
- Tx Fees (24h) - - - -
-
$0
+
+
+
+ {t('network.tx_fees', 'Tx Fees (24h)')} + + + +
+
$0
+
+
+
+ {t('network.tx_throughput', 'Tx Throughput')} + + +
-
-
- Tx Throughput - - - -
-
- {/* TODO remove this nanoticker dependency */} - {network.getIn(['stats', 'nanobrowse', 'CPSMedian_pr']) - ? `${network - .getIn(['stats', 'nanobrowse', 'CPSMedian_pr']) - .toFixed(1)} CPS` - : '-'} -
+
+ {/* TODO remove this nanoticker dependency */} + {network.getIn(['stats', 'nanobrowse', 'CPSMedian_pr']) + ? `${network + .getIn(['stats', 'nanobrowse', 'CPSMedian_pr']) + .toFixed(1)} CPS` + : '-'}{' '}
-
-
- Tx Speed (24h) - - - -
-
- {network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_24_hours'], - 0 - ) - ? convert_ms_to_readable_time( - network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_24_hours'], - 0 - ) +
+
+
+ {t('network.tx_speed', { time_range: '24h' }, 'Tx Speed (24h)')} + + + +
+
+ {network.getIn( + ['stats', 'nanodb', 'median_latency_ms_last_24_hours'], + 0 + ) + ? convert_ms_to_readable_time( + network.getIn( + ['stats', 'nanodb', 'median_latency_ms_last_24_hours'], + 0 ) - : '-'} -
+ ) + : '-'} +
+
+
+
+ {t('network.tx_speed', { time_range: '1h' }, 'Tx Speed (1h)')}
-
-
- Tx Speed (1h) - - - -
-
- {network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_hour'], - 0 - ) - ? convert_ms_to_readable_time( - network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_hour'], - 0 - ) +
+ {network.getIn(['stats', 'nanodb', 'median_latency_ms_last_hour'], 0) + ? convert_ms_to_readable_time( + network.getIn( + ['stats', 'nanodb', 'median_latency_ms_last_hour'], + 0 ) - : '-'} -
+ ) + : '-'} +
+
+
+
+ {t('network.tx_speed', { time_range: '10m' }, 'Tx Speed (10m)')}
-
-
- Tx Speed (10m) - - - -
-
- {network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_10_mins'], - 0 - ) - ? convert_ms_to_readable_time( - network.getIn( - ['stats', 'nanodb', 'median_latency_ms_last_10_mins'], - 0 - ) +
+ {network.getIn( + ['stats', 'nanodb', 'median_latency_ms_last_10_mins'], + 0 + ) + ? convert_ms_to_readable_time( + network.getIn( + ['stats', 'nanodb', 'median_latency_ms_last_10_mins'], + 0 ) - : '-'} -
+ ) + : '-'}
-
-
- Unconfirmed Blocks - - - -
-
- {unconfirmed_block_pool_count != null - ? format_number(unconfirmed_block_pool_count) - : '-'} -
+
+
+
+ {t('network.tx_backlog', 'Tx Backlog')} + + +
-
-
- Online Stake - - - -
-
- {/* TODO remove this nanoticker dependency */} - {network.getIn(['stats', 'nanobrowse', 'pStakeTotalStat']) - ? `${network - .getIn(['stats', 'nanobrowse', 'pStakeTotalStat']) - .toFixed(1)}%` - : '-'} -
+
+ {unconfirmed_block_pool_count != null + ? format_number(unconfirmed_block_pool_count) + : '-'}
-
-
Principal Reps
-
{stats.prCount || '-'}
+
+
+
+ {t('network.online_stake', 'Online Stake')} + + +
-
-
Total Reps (24h)
-
{network.getIn(['totalReps'], '-')}
+
+ {/* TODO remove this nanoticker dependency */} + {network.getIn(['stats', 'nanobrowse', 'pStakeTotalStat']) + ? `${network + .getIn(['stats', 'nanobrowse', 'pStakeTotalStat']) + .toFixed(1)}%` + : '-'}{' '}
-
-
Peers
-
{network.getIn(['stats', 'nanobrowse', 'peersMax'], '-')}
+
+
+
{t('network.principal_reps', 'Principal Reps')}
+
{stats.prCount || '-'}
+
+
+
{t('network.total_reps', 'Total Reps (24h)')}
+
{network.getIn(['totalReps'], '-')}
+
+
+
{t('common.peers', 'Peers')}
+
{network.getIn(['stats', 'nanobrowse', 'peersMax'], '-')}
+
+
+
+ {t('network.reps_to_confirm', 'Reps to Confirm')} + + +
-
-
- Reps to Confirm - - - -
-
{stats.confirmReps || '-'}
+
{stats.confirmReps || '-'}
+
+
+
+ {t('network.reps_to_censor', 'Reps to Censor or Stall')} + + +
-
-
- Reps to Censor or Stall - - - -
-
{stats.censorReps || '-'}
+
{stats.censorReps || '-'}
+
+
+
+ {t('network.energy_usage', 'Energy Usage (TDP) (24h)')} + + +
-
-
- Energy Usage (TDP) (24h) - - - -
-
- {wattHour ? `${((wattHour * 24) / 1000).toFixed(2)} kWh` : '-'} -
+
+ {wattHour ? `${((wattHour * 24) / 1000).toFixed(2)} kWh` : '-'}
- - NanoTicker -
- ) - } + + {t('network.nano_ticker', 'NanoTicker')} + +
+ ) } Network.propTypes = { diff --git a/src/views/components/representative-alerts/representative-alerts.js b/src/views/components/representative-alerts/representative-alerts.js index 99ac9f5e..4a4a7be2 100644 --- a/src/views/components/representative-alerts/representative-alerts.js +++ b/src/views/components/representative-alerts/representative-alerts.js @@ -12,6 +12,7 @@ import Chip from '@mui/material/Chip' import Tooltip from '@mui/material/Tooltip' import Skeleton from '@mui/material/Skeleton' import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' @@ -19,145 +20,178 @@ import './representative-alerts.styl' const ITEMS_LIMIT = 7 -const getTooltipText = (type) => { +const getTooltipText = ({ type, t }) => { switch (type) { case 'offline': - return 'Representative has stopped voting and appears offline.' + return t( + 'representative_alerts.tooltip.offline', + 'Representative has stopped voting and appears offline.' + ) case 'behind': - return 'Representative has fallen behind or is bootstrapping. The cutoff is a cemented count beyond the 95th percentile. (via telemetry)' + return t( + 'representative_alerts.tooltip.behind', + 'Representative has fallen behind or is bootstrapping. The cutoff is a cemented count beyond the 95th percentile. (via telemetry)' + ) case 'overweight': - return "Representative has beyond 3M Nano voting weight. Delegators should consider distributing the weight to improve the network's resilience and value." + return t( + 'representative_alerts.tooltip.overweight', + "Representative has beyond 3M Nano voting weight. Delegators should consider distributing the weight to improve the network's resilience and value." + ) case 'low uptime': - return 'Representative has been offline more than 25% in the last 28 days.' + return t( + 'representative_alerts.tooltip.low_uptime', + 'Representative has been offline more than 25% in the last 28 days.' + ) } } -export default class RepresentativeAlerts extends React.Component { - constructor(props) { - super(props) +export default function RepresentativeAlerts({ + items, + isLoading, + onlineWeight +}) { + const [expanded, setExpanded] = React.useState(false) + const { t } = useTranslation() - this.state = { - expanded: false - } - } - - handleClick = () => { - this.setState({ expanded: !this.state.expanded }) - } - - render() { - const { items, isLoading, onlineWeight } = this.props - - return ( - <> - - - + const handleClick = () => setExpanded(!expanded) + return ( + <> + +
+ + + + {t( + 'representative_alerts.table_header.representative', + 'Representative' + )} + + + {t('representative_alerts.table_header.issue', 'Issue')} + + + {t( + 'representative_alerts.table_header.last_online', + 'Last Online' + )} + + + {t('common.weight', 'Weight')} + + + {t( + 'representative_alerts.table_header.percent_online_weight', + '% Online Weight' + )} + + + {t('representative_alerts.table_header.behind', 'Behind')} + + + + + {isLoading && ( - Representative - Issue - Last Online - Weight - % Online Weight - Behind + + + + + + + + + + + + + + + + + + - - - {isLoading && ( - - - - - - + )} + {(expanded ? items : items.slice(0, ITEMS_LIMIT)).map( + (row, idx) => ( + + + + {row.account.alias || + `${row.account.account.slice(0, 15)}...`} + - + + + - - + + {row.account.is_online ? ( + + ) : row.account.last_online ? ( + timeago.format( + row.account.last_online * 1000, + 'nano_short' + ) + ) : ( + '' + )} - - + + {BigNumber(row.account.account_meta.weight) + .shiftedBy(-30) + .toFormat(0)} - - + + {row.account.account_meta.weight && onlineWeight + ? `${BigNumber(row.account.account_meta.weight) + .dividedBy(onlineWeight) + .multipliedBy(100) + .toFormat(2)} %` + : '-'} - - )} - {(this.state.expanded ? items : items.slice(0, ITEMS_LIMIT)).map( - (row, idx) => ( - - - - {row.account.alias || - `${row.account.account.slice(0, 15)}...`} - - - - - - - - - {row.account.is_online ? ( - - ) : row.account.last_online ? ( - timeago.format( - row.account.last_online * 1000, - 'nano_short' - ) - ) : ( - '' - )} - - - {BigNumber(row.account.account_meta.weight) - .shiftedBy(-30) - .toFormat(0)} - - - {row.account.account_meta.weight && onlineWeight - ? `${BigNumber(row.account.account_meta.weight) - .dividedBy(onlineWeight) - .multipliedBy(100) - .toFormat(2)} %` - : '-'} - - - {row.account.telemetry.cemented_behind >= 0 - ? BigNumber( - row.account.telemetry.cemented_behind - ).toFormat(0) - : '-'} - - - ) - )} - {items.length > ITEMS_LIMIT && ( - - - {this.state.expanded - ? 'Collapse' - : `Show ${items.length - ITEMS_LIMIT} more`} + + {row.account.telemetry.cemented_behind >= 0 + ? BigNumber( + row.account.telemetry.cemented_behind + ).toFormat(0) + : '-'} - )} - -
-
- - ) - } + ) + )} + {items.length > ITEMS_LIMIT && ( + + + {expanded + ? t('common.collapse', 'Collapse') + : t('common.show_more', { + count: items.length - ITEMS_LIMIT, + defaultValue: `Show ${ + items.length - ITEMS_LIMIT || 0 + } more` + })} + + + )} + + + + + ) } RepresentativeAlerts.propTypes = { diff --git a/src/views/components/representative-delegators/representative-delegators.js b/src/views/components/representative-delegators/representative-delegators.js index e8b27a0f..5ef8a11d 100644 --- a/src/views/components/representative-delegators/representative-delegators.js +++ b/src/views/components/representative-delegators/representative-delegators.js @@ -9,12 +9,14 @@ import TableHead from '@mui/material/TableHead' import TableRow from '@mui/material/TableRow' import LinearProgress from '@mui/material/LinearProgress' import { Link } from 'react-router-dom' +import { useTranslation } from 'react-i18next' import './representative-delegators.styl' const ITEMS_LIMIT = 10 export default function RepresentativeDelegators({ account }) { + const { t } = useTranslation() const [expanded, setExpanded] = useState(false) const handleClick = () => { @@ -30,8 +32,12 @@ export default function RepresentativeDelegators({ account }) { - Delegator - Balance + + {t('common.delegator', { count: 1, defaultValue: 'Delegator' })} + + + {t('common.balance', 'Balance')} + % of Total @@ -61,8 +67,12 @@ export default function RepresentativeDelegators({ account }) { {expanded - ? 'Collapse' - : `Show ${account.delegators.length - ITEMS_LIMIT} more`} + ? t('common.collapse', 'Collapse') + : t( + 'common.show_more', + { count: account.delegators.length - ITEMS_LIMIT }, + `Show ${account.delegators.length - ITEMS_LIMIT} more` + )} )} @@ -75,7 +85,10 @@ export default function RepresentativeDelegators({ account }) {
{!is_loading && (
- Showing top 100 delegators with a minimum balance of 1 Nano. + {t( + 'representative_delegators.showing_top_delegators', + 'Showing top 100 delegators with a minimum balance of 1 Nano.' + )}
)} diff --git a/src/views/components/representative-info/representative-info.js b/src/views/components/representative-info/representative-info.js index f9521124..583ca8e8 100644 --- a/src/views/components/representative-info/representative-info.js +++ b/src/views/components/representative-info/representative-info.js @@ -2,52 +2,50 @@ import React from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' import BigNumber from 'bignumber.js' import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' -export default class RepresentativeNetwork extends React.Component { - render() { - const { account } = this.props +export default function RepresentativeNetwork({ account }) { + const { t } = useTranslation() + const created_at = account.getIn(['representative_meta', 'created_at']) + const items = [ + { + label: t('representative_info.last_seen', 'Last Seen'), + value: account.get('is_online') ? ( + + ) : ( + timeago.format(account.getIn(['last_seen']) * 1000, 'nano_short') + ) + }, + { + label: t('representative_info.first_seen', 'First Seen'), + value: created_at ? timeago.format(created_at * 1000, 'nano_short') : '-' + } + ] - const createdAt = account.getIn(['representative_meta', 'created_at']) - const items = [ - { - label: 'Last Seen', - value: account.get('is_online') ? ( - - ) : ( - timeago.format(account.getIn(['last_seen']) * 1000, 'nano_short') - ) - }, - { - label: 'First Seen', - value: createdAt ? timeago.format(createdAt * 1000, 'nano_short') : '-' - } - ] + const rows = items.map((item, idx) => ( +
+
{item.label}
+
{item.value}
+
+ )) - const rows = items.map((i, idx) => ( -
-
{i.label}
-
{i.value}
-
- )) - - return ( -
-
-
- Weight Represented -
-
- {BigNumber(account.getIn(['account_meta', 'weight'])) - .shiftedBy(-30) - .toFormat(0)} -
+ return ( +
+
+
+ {t('representative_info.weight_represented', 'Weight Represented')} +
+
+ {BigNumber(account.getIn(['account_meta', 'weight'])) + .shiftedBy(-30) + .toFormat(0)}
- {rows}
- ) - } + {rows} +
+ ) } RepresentativeNetwork.propTypes = { diff --git a/src/views/components/representative-network/representative-network.js b/src/views/components/representative-network/representative-network.js index 0b0b3935..3de5fc79 100644 --- a/src/views/components/representative-network/representative-network.js +++ b/src/views/components/representative-network/representative-network.js @@ -1,45 +1,43 @@ import React from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' +import { useTranslation } from 'react-i18next' -export default class RepresentativeNetwork extends React.Component { - render() { - const { account } = this.props +export default function RepresentativeNetwork({ account }) { + const { t } = useTranslation() + const items = [ + { + label: t('representative_network.provider', 'Provider'), + value: account.getIn(['network', 'asname']) + }, + { + label: t('representative_network.isp', 'ISP'), + value: account.getIn(['network', 'isp']) + }, + { + label: t('common.country', 'Country'), + value: account.getIn(['network', 'country']) + }, + { + label: t('representative_network.city', 'City'), + value: account.getIn(['network', 'city']) + } + ] - const items = [ - { - label: 'Provider', - value: account.getIn(['network', 'asname']) - }, - { - label: 'ISP', - value: account.getIn(['network', 'isp']) - }, - { - label: 'Country', - value: account.getIn(['network', 'country']) - }, - { - label: 'City', - value: account.getIn(['network', 'city']) - } - ] + const rows = items.map((i, idx) => ( +
+
{i.label}
+
{i.value}
+
+ )) - const rows = items.map((i, idx) => ( -
-
{i.label}
-
{i.value}
+ return ( +
+
+ {t('representative_network.network', 'Network')}
- )) - - return ( -
-
- Network -
- {rows} -
- ) - } + {rows} +
+ ) } RepresentativeNetwork.propTypes = { diff --git a/src/views/components/representative-telemetry-chart/representative-telemetry-chart.js b/src/views/components/representative-telemetry-chart/representative-telemetry-chart.js index ce73622c..a0d0d280 100644 --- a/src/views/components/representative-telemetry-chart/representative-telemetry-chart.js +++ b/src/views/components/representative-telemetry-chart/representative-telemetry-chart.js @@ -43,11 +43,7 @@ export default class RepresentativeTelemetryChart extends React.Component { ] } - return ( - <> - - - ) + return } } diff --git a/src/views/components/representative-telemetry/representative-telemetry.js b/src/views/components/representative-telemetry/representative-telemetry.js index dbf1cf2d..fe2594dd 100644 --- a/src/views/components/representative-telemetry/representative-telemetry.js +++ b/src/views/components/representative-telemetry/representative-telemetry.js @@ -1,91 +1,92 @@ import React from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' import BigNumber from 'bignumber.js' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' -export default class RepresentativeTelemetry extends React.Component { - render() { - const { account } = this.props +export default function RepresentativeTelemetry({ account }) { + const { t } = useTranslation() + const bandwidth = account.getIn(['telemetry', 'bandwidth_cap']) + const bandwidth_value = bandwidth + ? `${(bandwidth / (1024 * 1024)).toFixed(1)}Mb` + : typeof bandwidth !== 'undefined' + ? t('common.unlimited', 'Unlimited') + : '-' - const bandwidth = account.getIn(['telemetry', 'bandwidth_cap']) - const bandwidthValue = bandwidth - ? `${(bandwidth / (1024 * 1024)).toFixed(1)}Mb` - : typeof bandwidth !== 'undefined' - ? 'Unlimited' - : '-' + const block_count = account.getIn(['telemetry', 'block_count'], 0) + const block_behind = account.getIn(['telemetry', 'block_behind'], 0) + const cemented_count = account.getIn(['telemetry', 'cemented_count'], 0) + const cemented_behind = account.getIn(['telemetry', 'cemented_behind'], 0) + const unchecked_count = account.getIn(['telemetry', 'unchecked_count'], 0) + const telemetry_timestamp = account.getIn( + ['telemetry', 'telemetry_timestamp'], + 0 + ) - const blockCount = account.getIn(['telemetry', 'block_count'], 0) - const blockBehind = account.getIn(['telemetry', 'block_behind'], 0) - const cementedCount = account.getIn(['telemetry', 'cemented_count'], 0) - const cementedBehind = account.getIn(['telemetry', 'cemented_behind'], 0) - const uncheckedCount = account.getIn(['telemetry', 'unchecked_count'], 0) - const telemetryTimestamp = account.getIn( - ['telemetry', 'telemetry_timestamp'], - 0 - ) + const items = [ + { + label: t('common.peers', 'Peers'), + value: account.getIn(['telemetry', 'peer_count'], '-') + }, + { + label: t('common.port', 'Port'), + value: account.getIn(['telemetry', 'port'], '-') + }, + { + label: t('common.version', 'Version'), + value: account.getIn(['version'], '-') + }, + { + label: t('common.bandwidth_limit', 'Bandwidth Limit'), + value: bandwidth_value + }, + { + label: t('common.blocks', 'Blocks'), + value: block_count ? BigNumber(block_count).toFormat() : '-' + }, + { + label: t('common.blocks_behind', 'Blocks Behind'), + value: block_behind ? BigNumber(block_behind).toFormat() : '-' + }, + { + label: t('common.conf_short', 'Conf.'), + value: cemented_count ? BigNumber(cemented_count).toFormat() : '-' + }, + { + label: t('common.conf_diff_short', 'Conf. Diff'), + value: cemented_behind ? BigNumber(cemented_behind).toFormat() : '-' + }, + { + label: t('common.unchecked', 'Unchecked'), + value: unchecked_count ? BigNumber(unchecked_count).toFormat() : '-' + }, + { + label: t( + 'representative_telemetry.telemetry_timestamp', + 'Telemetry Timestamp' + ), + value: telemetry_timestamp + ? timeago.format(telemetry_timestamp * 1000, 'nano_short') + : '-' + } + ] - const items = [ - { - label: 'Peers', - value: account.getIn(['telemetry', 'peer_count'], '-') - }, - { - label: 'Port', - value: account.getIn(['telemetry', 'port'], '-') - }, - { - label: 'Version', - value: account.getIn(['version'], '-') - }, - { - label: 'Bandwidth Limit', - value: bandwidthValue - }, - { - label: 'Blocks', - value: blockCount ? BigNumber(blockCount).toFormat() : '-' - }, - { - label: 'Blocks Diff', - value: blockBehind ? BigNumber(blockBehind).toFormat() : '-' - }, - { - label: 'Conf.', - value: cementedCount ? BigNumber(cementedCount).toFormat() : '-' - }, - { - label: 'Conf. Diff', - value: cementedBehind ? BigNumber(cementedBehind).toFormat() : '-' - }, - { - label: 'Unchecked', - value: uncheckedCount ? BigNumber(uncheckedCount).toFormat() : '-' - }, - { - label: 'Telemetry Timestamp', - value: telemetryTimestamp - ? timeago.format(telemetryTimestamp * 1000, 'nano_short') - : '-' - } - ] + const rows = items.map((item, idx) => ( +
+
{item.label}
+
{item.value}
+
+ )) - const rows = items.map((i, idx) => ( -
-
{i.label}
-
{i.value}
+ return ( +
+
+ {t('representative_telemetry.telemetry', 'Telemetry')}
- )) - - return ( -
-
- Telemetry -
- {rows} -
- ) - } + {rows} +
+ ) } RepresentativeTelemetry.propTypes = { diff --git a/src/views/components/representative-uptime/representative-uptime.js b/src/views/components/representative-uptime/representative-uptime.js index ca77d6e3..7fded899 100644 --- a/src/views/components/representative-uptime/representative-uptime.js +++ b/src/views/components/representative-uptime/representative-uptime.js @@ -1,125 +1,137 @@ import React from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' import * as timeago from 'timeago.js' +import { useTranslation } from 'react-i18next' import Uptime from '@components/uptime' import './representative-uptime.styl' -export default class RepresentativeUptime extends React.Component { - render() { - const { uptime } = this.props.account.toJS() +export default function RepresentativeUptime({ account }) { + const { t } = useTranslation() - const lastOnline = this.props.account.get('last_online') - const lastOffline = this.props.account.get('last_offline') + const { uptime } = account.toJS() - const onlineCount = uptime.filter((i) => i.online).length - const last60 = this.props.account.getIn(['uptime_summary', 'days_60'], {}) - const last60Pct = - Math.round( - (last60.online_count / (last60.online_count + last60.offline_count)) * - 10000 - ) / 100 - const last60Class = - last60Pct > 95 - ? 'online' - : last60Pct < 70 - ? 'offline' - : last60Pct < 80 - ? 'warning' - : '' + const last_online = account.get('last_online') + const last_offline = account.get('last_offline') - const last90 = this.props.account.getIn(['uptime_summary', 'days_90'], {}) - const last90Pct = - Math.round( - (last90.online_count / (last90.online_count + last90.offline_count)) * - 10000 - ) / 100 - const last90Class = - last90Pct > 95 ? 'online' : last90Pct < 80 ? 'offline' : '' + const online_count = uptime.filter((i) => i.online).length + const last_60 = account.getIn(['uptime_summary', 'days_60'], {}) + const last_60_pct = + Math.round( + (last_60.online_count / (last_60.online_count + last_60.offline_count)) * + 10000 + ) / 100 + const last_60_class = + last_60_pct > 95 + ? t('common.online', 'online') + : last_60_pct < 70 + ? t('common.offline', 'offline') + : last_60_pct < 80 + ? t('representative_uptime.warning', 'warning') + : '' - let text - let online = true - if (!lastOffline) { - // missing both - if (!lastOnline) { - text = 'Operational' - } else { - // missing offline, has online - text = 'Operational' - } - } else if (!lastOnline) { - // missing online, has offline - text = 'Down' - online = false + const last_90 = account.getIn(['uptime_summary', 'days_90'], {}) + const last_90_pct = + Math.round( + (last_90.online_count / (last_90.online_count + last_90.offline_count)) * + 10000 + ) / 100 + const last_90_class = + last_90_pct > 95 + ? t('common.online', 'online') + : last_90_pct < 80 + ? t('common.offline', 'offline') + : '' + + let text + let online = true + if (!last_offline) { + // missing both + if (!last_online) { + text = t('representative_uptime.operational', 'Operational') } else { - // has both - if (lastOnline > lastOffline) { - text = `Up for ${timeago.format(lastOffline * 1000, 'nano_short')}` - } else { - text = `Down for ${timeago.format(lastOnline * 1000, 'nano_short')}` - online = false - } + // missing offline, has online + text = t('representative_uptime.operational', 'Operational') } + } else if (!last_online) { + // missing online, has offline + text = t('representative_uptime.down', 'Down') + online = false + } else { + // has both + if (last_online > last_offline) { + text = `${t('representative_uptime.up_for', 'Up for')} ${timeago.format( + last_offline * 1000, + 'nano_short' + )}` + } else { + text = `${t( + 'representative_uptime.down_for', + 'Down for' + )} ${timeago.format(last_online * 1000, 'nano_short')}` + online = false + } + } - const uptimePct = Math.round((onlineCount / uptime.length) * 10000) / 100 - const uptimeClass = - uptimePct > 90 - ? 'online' - : uptimePct < 50 - ? 'offline' - : uptimePct < 75 - ? 'warning' - : '' + const uptime_pct = Math.round((online_count / uptime.length) * 10000) / 100 + const uptime_class = + uptime_pct > 90 + ? t('common.online', 'online') + : uptime_pct < 50 + ? t('common.offline', 'offline') + : uptime_pct < 75 + ? t('representative_uptime.warning', 'warning') + : '' - return ( -
-
-
-
- Current Status -
-
- {text} -
+ return ( +
+
+
+
+ {t('representative_uptime.current_status', 'Current Status')} +
+
+ {text}
-
-
- 2W Uptime -
-
- {uptimePct}% -
+
+
+
+ {t('representative_uptime.2w_uptime', '2W Uptime')} +
+
+ {uptime_pct}%
-
-
- 2M Uptime -
-
- {last60Pct ? `${last60Pct}%` : '-'} -
+
+
+
+ {t('representative_uptime.2m_uptime', '2M Uptime')}
-
-
- 3M Uptime -
-
- {last90Pct ? `${last90Pct}%` : '-'} -
+
+ {last_60_pct ? `${last_60_pct}%` : '-'}
-
- +
+
+ {t('representative_uptime.3m_uptime', '3M Uptime')} +
+
+ {last_90_pct ? `${last_90_pct}%` : '-'} +
- ) - } +
+ +
+
+ ) } RepresentativeUptime.propTypes = { diff --git a/src/views/components/representatives-bandwidth-by-weight/representatives-bandwidth-by-weight.js b/src/views/components/representatives-bandwidth-by-weight/representatives-bandwidth-by-weight.js index be04e8e2..5798027c 100644 --- a/src/views/components/representatives-bandwidth-by-weight/representatives-bandwidth-by-weight.js +++ b/src/views/components/representatives-bandwidth-by-weight/representatives-bandwidth-by-weight.js @@ -1,23 +1,25 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesBandwidthByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesBandwidthByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesBandwidthByWeight.propTypes = { diff --git a/src/views/components/representatives-cemented-by-weight/representatives-cemented-by-weight.js b/src/views/components/representatives-cemented-by-weight/representatives-cemented-by-weight.js index c19f8e65..c1e48394 100644 --- a/src/views/components/representatives-cemented-by-weight/representatives-cemented-by-weight.js +++ b/src/views/components/representatives-cemented-by-weight/representatives-cemented-by-weight.js @@ -1,23 +1,28 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesCementedByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesCementedByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesCementedByWeight.propTypes = { diff --git a/src/views/components/representatives-checked-by-weight/representatives-checked-by-weight.js b/src/views/components/representatives-checked-by-weight/representatives-checked-by-weight.js index a56a318a..fd9f0e7f 100644 --- a/src/views/components/representatives-checked-by-weight/representatives-checked-by-weight.js +++ b/src/views/components/representatives-checked-by-weight/representatives-checked-by-weight.js @@ -1,23 +1,28 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesCheckedByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesCheckedByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesCheckedByWeight.propTypes = { diff --git a/src/views/components/representatives-cluster-charts/representatives-cluster-charts.js b/src/views/components/representatives-cluster-charts/representatives-cluster-charts.js index 294ea1fe..fed1da63 100644 --- a/src/views/components/representatives-cluster-charts/representatives-cluster-charts.js +++ b/src/views/components/representatives-cluster-charts/representatives-cluster-charts.js @@ -10,6 +10,7 @@ import { TooltipComponent, SingleAxisComponent } from 'echarts/components' +import { useTranslation } from 'react-i18next' import { CanvasRenderer } from 'echarts/renderers' @@ -21,204 +22,202 @@ echarts.use([ CanvasRenderer ]) -export default class RepresentativesClusterCharts extends React.Component { - render() { - const { accounts, totalWeight } = this.props +export default function RepresentativesClusterCharts({ + accounts, + totalWeight +}) { + const { t } = useTranslation() + const confirmations_data = [] + const blocks_data = [] + const peers_data = [] + const bandwidth_data = [] + const unchecked_data = [] + accounts.forEach((a) => { + if (a.telemetry.cemented_behind > 1000) return + const weight = BigNumber(a.account_meta.weight) + .dividedBy(totalWeight) + .multipliedBy(100) + .toFixed() + const label = a.alias || a.account + confirmations_data.push([a.telemetry.cemented_behind, weight, label]) + blocks_data.push([a.telemetry.block_behind, weight, label]) + peers_data.push([a.telemetry.peer_count, weight, label]) + unchecked_data.push([a.telemetry.unchecked_count, weight, label]) - const confirmationsData = [] - const blocksData = [] - const peersData = [] - const bandwidthData = [] - const uncheckedData = [] - accounts.forEach((a) => { - if (a.telemetry.cemented_behind > 1000) return - const weight = BigNumber(a.account_meta.weight) - .dividedBy(totalWeight) - .multipliedBy(100) - .toFixed() - const label = a.alias || a.account - confirmationsData.push([a.telemetry.cemented_behind, weight, label]) - blocksData.push([a.telemetry.block_behind, weight, label]) - peersData.push([a.telemetry.peer_count, weight, label]) - uncheckedData.push([a.telemetry.unchecked_count, weight, label]) + // exclude 0 (unlimited) + if (a.telemetry.bandwidth_cap) + bandwidth_data.push([ + a.telemetry.bandwidth_cap / (1024 * 1024), + weight, + label + ]) + }) - // exclude 0 (unlimited) - if (a.telemetry.bandwidth_cap) - bandwidthData.push([ - a.telemetry.bandwidth_cap / (1024 * 1024), - weight, - label - ]) - }) - - const seriesCommon = { - type: 'scatter', - coordinateSystem: 'singleAxis', - symbolSize: (dataItem) => Math.min(Math.max(dataItem[1] * 6, 6), 35), - labelLine: { - show: true, - length2: 2, - lineStyle: { - color: '#bbb' - } - }, - label: { - show: true, - formatter: (param) => param.data[2], - minMargin: 10 - }, - tooltip: { - className: 'echarts-tooltip', - formatter: (params) => params.data[2] + const series_common = { + type: 'scatter', + coordinateSystem: 'singleAxis', + symbolSize: (data_item) => Math.min(Math.max(data_item[1] * 6, 6), 35), + labelLine: { + show: true, + length2: 2, + lineStyle: { + color: '#bbb' } + }, + label: { + show: true, + formatter: (param) => param.data[2], + minMargin: 10 + }, + tooltip: { + className: 'echarts-tooltip', + formatter: (params) => params.data[2] } + } - const titleCommon = { - left: 'center', - textStyle: { - fontWeight: 'normal', - fontFamily: 'IBM Plex Mono' - } + const title_common = { + left: 'center', + textStyle: { + fontWeight: 'normal', + fontFamily: 'IBM Plex Mono' } + } - const option = { - tooltip: { - className: 'echarts-tooltip', - position: 'top' + const option = { + tooltip: { + className: 'echarts-tooltip', + position: 'top' + }, + title: [ + { + text: t('common.confirmations_behind', 'Confirmations Behind'), + top: 20, + ...title_common }, - title: [ - { - text: 'Confirmations Behind', - top: 20, - ...titleCommon - }, - { - text: 'Blocks Behind', - top: 140, - ...titleCommon - }, - { - text: 'Unchecked Count', - top: 260, - ...titleCommon - }, - { - text: 'Bandwidth Limit', - top: 380, - ...titleCommon - }, - { - text: 'Peer Count', - top: 500, - ...titleCommon + { + text: t('common.blocks_behind', 'Blocks Behind'), + top: 140, + ...title_common + }, + { + text: t('common.unchecked_count', 'Unchecked Count'), + top: 260, + ...title_common + }, + { + text: t('common.bandwidth_limit', 'Bandwidth Limit'), + top: 380, + ...title_common + }, + { + text: t('common.peers', 'Peers'), + top: 500, + ...title_common + } + ], + singleAxis: [ + { + type: 'value', + height: '100px', + top: 0 + }, + { + type: 'value', + top: '120px', + height: '100px' + }, + { + scale: true, + type: 'value', + top: '240px', + height: '100px' + }, + { + type: 'value', + top: '360px', + height: '100px', + axisLabel: { + formatter: (value) => `${value} mb/s` } - ], - singleAxis: [ - { - type: 'value', - height: '100px', - top: 0 - }, - { - type: 'value', - top: '120px', - height: '100px' - }, - { - scale: true, - type: 'value', - top: '240px', - height: '100px' - }, - { - type: 'value', - top: '360px', - height: '100px', - axisLabel: { - formatter: (value) => `${value} mb/s` - } + }, + { + scale: true, + type: 'value', + top: '480px', + height: '100px' + } + ], + series: [ + { + singleAxisIndex: 0, + labelLayout: { + y: 80, + align: 'left', + hideOverlap: true, + width: 20, + overflow: 'truncate' }, - { - scale: true, - type: 'value', - top: '480px', - height: '100px' - } - ], - series: [ - { - singleAxisIndex: 0, - labelLayout: { - y: 80, - align: 'left', - hideOverlap: true, - width: 20, - overflow: 'truncate' - }, - data: confirmationsData, - ...seriesCommon + data: confirmations_data, + ...series_common + }, + { + singleAxisIndex: 1, + labelLayout: { + y: 200, + align: 'left', + hideOverlap: true, + width: 20, + overflow: 'truncate' }, - { - singleAxisIndex: 1, - labelLayout: { - y: 200, - align: 'left', - hideOverlap: true, - width: 20, - overflow: 'truncate' - }, - data: blocksData, - ...seriesCommon + data: blocks_data, + ...series_common + }, + { + singleAxisIndex: 2, + labelLayout: { + y: 320, + align: 'left', + hideOverlap: true, + width: 20, + overflow: 'truncate' }, - { - singleAxisIndex: 2, - labelLayout: { - y: 320, - align: 'left', - hideOverlap: true, - width: 20, - overflow: 'truncate' - }, - data: uncheckedData, - ...seriesCommon + data: unchecked_data, + ...series_common + }, + { + singleAxisIndex: 3, + labelLayout: { + y: 440, + align: 'left', + hideOverlap: true, + width: 20, + overflow: 'truncate' }, - { - singleAxisIndex: 3, - labelLayout: { - y: 440, - align: 'left', - hideOverlap: true, - width: 20, - overflow: 'truncate' - }, - data: bandwidthData, - ...seriesCommon + data: bandwidth_data, + ...series_common + }, + { + singleAxisIndex: 4, + labelLayout: { + y: 560, + align: 'left', + hideOverlap: true, + width: 20, + overflow: 'truncate' }, - { - singleAxisIndex: 4, - labelLayout: { - y: 560, - align: 'left', - hideOverlap: true, - width: 20, - overflow: 'truncate' - }, - data: peersData, - ...seriesCommon - } - ] - } - - return ( - <> - - - ) + data: peers_data, + ...series_common + } + ] } + + return ( + + ) } RepresentativesClusterCharts.propTypes = { diff --git a/src/views/components/representatives-country-by-weight/representatives-country-by-weight.js b/src/views/components/representatives-country-by-weight/representatives-country-by-weight.js index 90fc25f5..c4d0ee57 100644 --- a/src/views/components/representatives-country-by-weight/representatives-country-by-weight.js +++ b/src/views/components/representatives-country-by-weight/representatives-country-by-weight.js @@ -1,22 +1,21 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesCountryByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesCountryByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesCountryByWeight.propTypes = { diff --git a/src/views/components/representatives-filters/representatives-filters.js b/src/views/components/representatives-filters/representatives-filters.js index 46c145a8..038b4aa3 100644 --- a/src/views/components/representatives-filters/representatives-filters.js +++ b/src/views/components/representatives-filters/representatives-filters.js @@ -1,27 +1,27 @@ import React from 'react' import PropTypes from 'prop-types' import ClearIcon from '@mui/icons-material/Clear' +import { useTranslation } from 'react-i18next' import './representatives-filters.styl' -export default class RepresentativesFilters extends React.Component { - handleClick = () => { +export default function RepresentativesFilters({ filter, field }) { + const { t } = useTranslation() + const handleClick = () => { // clear filters - this.props.filter() + filter() } - render() { - if (!this.props.field) { - return null - } - - return ( -
- -
Clear filters
-
- ) + if (!field) { + return null } + + return ( +
+ +
{t('common.clear_filters', 'Clear Filters')}
+
+ ) } RepresentativesFilters.propTypes = { diff --git a/src/views/components/representatives-offline/representatives-offline.js b/src/views/components/representatives-offline/representatives-offline.js index d4cccb74..4048786f 100644 --- a/src/views/components/representatives-offline/representatives-offline.js +++ b/src/views/components/representatives-offline/representatives-offline.js @@ -1,6 +1,5 @@ import React from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' -import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' import { Link } from 'react-router-dom' import Table from '@mui/material/Table' @@ -9,64 +8,66 @@ import TableCell from '@mui/material/TableCell' import TableContainer from '@mui/material/TableContainer' import TableHead from '@mui/material/TableHead' import TableRow from '@mui/material/TableRow' +import { useTranslation } from 'react-i18next' import { timeago } from '@core/utils' import './representatives-offline.styl' -export default class RepresentativesOffline extends React.Component { - render() { - const { accounts } = this.props +export default function RepresentativesOffline({ accounts }) { + const { t } = useTranslation() - const rows = accounts - .filter((a) => !a.is_online) - .map((p) => { - return { - account: p.account, - alias: p.alias, - is_online: p.is_online, - weight: p.account_meta.weight || 0, - last_online: p.last_online, - diff: (p.last_online || 0) - (p.last_offline || 0) - } - }) + const rows = accounts + .filter((a) => !a.is_online) + .map((p) => { + return { + account: p.account, + alias: p.alias, + is_online: p.is_online, + weight: p.account_meta.weight || 0, + last_online: p.last_online, + diff: (p.last_online || 0) - (p.last_offline || 0) + } + }) - const sorted = rows.sort((a, b) => b.weight - a.weight) + const sorted = rows.sort((a, b) => b.weight - a.weight) - return ( - - - - - Offline Account - Last Online - Weight + return ( + +
+ + + + {t('representatives_offline.account', 'Offline Account')} + + + {t('representatives_offline.last_online', 'Last Online')} + + {t('common.weight', 'Weight')} + + + + {sorted.map((row) => ( + + + + {row.alias || `${row.account.slice(0, 15)}...`} + + + + {timeago.format(row.last_online * 1000, 'nano_short')} + + + {BigNumber(row.weight).shiftedBy(-30).toFormat(0)} + - - - {sorted.map((row) => ( - - - - {row.alias || `${row.account.slice(0, 15)}...`} - - - - {timeago.format(row.last_online * 1000, 'nano_short')} - - - {BigNumber(row.weight).shiftedBy(-30).toFormat(0)} - - - ))} - -
-
- ) - } + ))} + + + + ) } RepresentativesOffline.propTypes = { - accounts: ImmutablePropTypes.map, - totalWeight: PropTypes.number + accounts: ImmutablePropTypes.map } diff --git a/src/views/components/representatives-provider-by-weight/representatives-provider-by-weight.js b/src/views/components/representatives-provider-by-weight/representatives-provider-by-weight.js index fafb3430..74557723 100644 --- a/src/views/components/representatives-provider-by-weight/representatives-provider-by-weight.js +++ b/src/views/components/representatives-provider-by-weight/representatives-provider-by-weight.js @@ -1,22 +1,21 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesProviderByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesProviderByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesProviderByWeight.propTypes = { diff --git a/src/views/components/representatives-quorum-charts/representatives-quorum-charts.js b/src/views/components/representatives-quorum-charts/representatives-quorum-charts.js index 722cbd84..563da20d 100644 --- a/src/views/components/representatives-quorum-charts/representatives-quorum-charts.js +++ b/src/views/components/representatives-quorum-charts/representatives-quorum-charts.js @@ -1,230 +1,230 @@ -import React from 'react' +import React, { useEffect } from 'react' import PropTypes from 'prop-types' import BigNumber from 'bignumber.js' import ReactEChartsCore from 'echarts-for-react/lib/core' import * as echarts from 'echarts/core' import { LineChart } from 'echarts/charts' import { TitleComponent, TooltipComponent } from 'echarts/components' +import { useTranslation } from 'react-i18next' import { CanvasRenderer } from 'echarts/renderers' echarts.use([TitleComponent, TooltipComponent, LineChart, CanvasRenderer]) -export default class RepresentativesQuorumCharts extends React.Component { - componentDidMount() { - this.props.load() - } +export default function RepresentativesQuorumCharts({ data, peerData, load }) { + const { t } = useTranslation() - render() { - const { data, peerData } = this.props - const commonOptions = { - tooltip: { - className: 'echarts-tooltip', - trigger: 'axis', - formatter: (p) => { - const values = p.map( - (s) => - `${s.marker} ${s.data[2]} - ${BigNumber(s.data[1]).toFormat(0)}M` - ) + useEffect(() => { + load() + }, [load]) - values.unshift(p[0].axisValueLabel) + const commonOptions = { + tooltip: { + className: 'echarts-tooltip', + trigger: 'axis', + formatter: (p) => { + const values = p.map( + (s) => + `${s.marker} ${s.data[2]} - ${BigNumber(s.data[1]).toFormat(0)}M` + ) - return values.join('
') - } - }, - xAxis: { - type: 'time' - }, - yAxis: { - type: 'value', - scale: true, - axisLabel: { - formatter: (value) => `${value}M` - } + values.unshift(p[0].axisValueLabel) + + return values.join('
') + } + }, + xAxis: { + type: 'time' + }, + yAxis: { + type: 'value', + scale: true, + axisLabel: { + formatter: (value) => `${value}M` } } + } - const commonTitle = { - top: 10, - left: 'center', - textStyle: { - fontWeight: 'normal', - fontFamily: 'IBM Plex Mono' - } + const commonTitle = { + top: 10, + left: 'center', + textStyle: { + fontWeight: 'normal', + fontFamily: 'IBM Plex Mono' } + } - const onlineOption = { - color: ['#5470c6', 'red', '#5470c6'], - title: { - text: 'Online Weight', - ...commonTitle + const onlineOption = { + color: ['#5470c6', 'red', '#5470c6'], + title: { + text: t('representatives_quorum_chart.title', 'Online Weight'), + ...commonTitle + }, + series: [ + { + type: 'line', + showSymbol: false, + data: data.online_stake_total.max, + areaStyle: {}, + lineStyle: { + opacity: 0 + } }, - series: [ - { - type: 'line', - showSymbol: false, - data: data.online_stake_total.max, - areaStyle: {}, - lineStyle: { - opacity: 0 - } - }, - { - type: 'line', - showSymbol: false, - data: data.online_stake_total.median, - lineStyle: { - color: 'red' - } - }, - { - type: 'line', - showSymbol: false, - data: data.online_stake_total.min, - areaStyle: { - color: 'white', - opacity: 1 - }, - lineStyle: { - opacity: 0 - } + { + type: 'line', + showSymbol: false, + data: data.online_stake_total.median, + lineStyle: { + color: 'red' } - ], - ...commonOptions - } - - const trendedOption = { - color: ['#5470c6', 'red', '#5470c6'], - title: { - text: 'Trended Weight', - ...commonTitle }, - series: [ - { - type: 'line', - showSymbol: false, - data: data.trended_stake_total.max, - areaStyle: {}, - lineStyle: { - opacity: 0 - } - }, - { - type: 'line', - showSymbol: false, - data: data.trended_stake_total.median, - lineStyle: { - color: 'red' - } + { + type: 'line', + showSymbol: false, + data: data.online_stake_total.min, + areaStyle: { + color: 'white', + opacity: 1 }, - { - type: 'line', - showSymbol: false, - data: data.trended_stake_total.min, - areaStyle: { - color: 'white', - opacity: 1 - }, - lineStyle: { - opacity: 0 - } + lineStyle: { + opacity: 0 } - ], - ...commonOptions - } + } + ], + ...commonOptions + } - const peersOption = { - ...commonOptions, - title: { - text: 'Peers Weight', - ...commonTitle + const trendedOption = { + color: ['#5470c6', 'red', '#5470c6'], + title: { + text: t('representatives_quorum_chart.trended_weight', 'Trended Weight'), + ...commonTitle + }, + series: [ + { + type: 'line', + showSymbol: false, + data: data.trended_stake_total.max, + areaStyle: {}, + lineStyle: { + opacity: 0 + } }, - series: peerData.map((data) => ({ + { type: 'line', showSymbol: false, - data - })), - tooltip: { - className: 'echarts-tooltip', - trigger: 'axis', - formatter: (p) => { - const values = p.map( - (s) => - `${s.marker} ${BigNumber(s.data[1]).toFormat(0)}M - ${ - new URL(s.data[2]).hostname - }` - ) - values.unshift(p[0].axisValueLabel) - return values.join('
') + data: data.trended_stake_total.median, + lineStyle: { + color: 'red' + } + }, + { + type: 'line', + showSymbol: false, + data: data.trended_stake_total.min, + areaStyle: { + color: 'white', + opacity: 1 + }, + lineStyle: { + opacity: 0 } } + ], + ...commonOptions + } + + const peersOption = { + ...commonOptions, + title: { + text: t('representatives_quorum_chart.peers_weight', 'Peers Weight'), + ...commonTitle + }, + series: peerData.map((data) => ({ + type: 'line', + showSymbol: false, + data + })), + tooltip: { + className: 'echarts-tooltip', + trigger: 'axis', + formatter: (p) => { + const values = p.map( + (s) => + `${s.marker} ${BigNumber(s.data[1]).toFormat(0)}M - ${ + new URL(s.data[2]).hostname + }` + ) + values.unshift(p[0].axisValueLabel) + return values.join('
') + } } + } - const quorumOption = { - color: ['#5470c6', 'red', '#5470c6'], - title: { - text: 'Quorum Delta', - ...commonTitle + const quorumOption = { + color: ['#5470c6', 'red', '#5470c6'], + title: { + text: t('common.quorum_delta', 'Quorum Delta'), + ...commonTitle + }, + series: [ + { + type: 'line', + showSymbol: false, + data: data.quorum_delta.max, + areaStyle: {}, + lineStyle: { + opacity: 0 + } }, - series: [ - { - type: 'line', - showSymbol: false, - data: data.quorum_delta.max, - areaStyle: {}, - lineStyle: { - opacity: 0 - } - }, - { - type: 'line', - showSymbol: false, - data: data.quorum_delta.median, - lineStyle: { - color: 'red' - } + { + type: 'line', + showSymbol: false, + data: data.quorum_delta.median, + lineStyle: { + color: 'red' + } + }, + { + type: 'line', + showSymbol: false, + data: data.quorum_delta.min, + areaStyle: { + color: 'white', + opacity: 1 }, - { - type: 'line', - showSymbol: false, - data: data.quorum_delta.min, - areaStyle: { - color: 'white', - opacity: 1 - }, - lineStyle: { - opacity: 0 - } + lineStyle: { + opacity: 0 } - ], - ...commonOptions - } - - return ( - <> - - - - - - ) + } + ], + ...commonOptions } + + return ( + <> + + + + + + ) } RepresentativesQuorumCharts.propTypes = { diff --git a/src/views/components/representatives-search/representatives-search.js b/src/views/components/representatives-search/representatives-search.js index a35f2021..7e88af5f 100644 --- a/src/views/components/representatives-search/representatives-search.js +++ b/src/views/components/representatives-search/representatives-search.js @@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react' import PropTypes from 'prop-types' import ClearIcon from '@mui/icons-material/Clear' import KeyboardCommandKeyIcon from '@mui/icons-material/KeyboardCommandKey' +import { useTranslation } from 'react-i18next' import { debounce } from '@core/utils' @@ -12,6 +13,7 @@ const RepresentativesSearch = ({ search, align = 'center' }) => { + const { t } = useTranslation() const [value, setValue] = useState(initialValue || '') const inputRef = useRef(null) @@ -59,7 +61,10 @@ const RepresentativesSearch = ({ ref={inputRef} className='search__input' type='text' - placeholder='Filter by account, alias, ip' + placeholder={t( + 'representatives_search.placeholder', + 'Filter by account, alias, ip' + )} value={value} onChange={handleChange} /> diff --git a/src/views/components/representatives-version-by-weight/representatives-version-by-weight.js b/src/views/components/representatives-version-by-weight/representatives-version-by-weight.js index 4a3f0954..858a2276 100644 --- a/src/views/components/representatives-version-by-weight/representatives-version-by-weight.js +++ b/src/views/components/representatives-version-by-weight/representatives-version-by-weight.js @@ -1,22 +1,21 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import MetricCard from '@components/metric-card' -export default class RepresentativesVersionByWeight extends React.Component { - render() { - const { metrics } = this.props - return ( - - ) - } +export default function RepresentativesVersionByWeight({ metrics }) { + const { t } = useTranslation() + return ( + + ) } RepresentativesVersionByWeight.propTypes = { diff --git a/src/views/components/representatives-weight-chart/representatives-weight-chart.js b/src/views/components/representatives-weight-chart/representatives-weight-chart.js index 4e676ddb..c40eb0bf 100644 --- a/src/views/components/representatives-weight-chart/representatives-weight-chart.js +++ b/src/views/components/representatives-weight-chart/representatives-weight-chart.js @@ -6,6 +6,7 @@ import BigNumber from 'bignumber.js' import * as echarts from 'echarts/core' import { PieChart } from 'echarts/charts' import { TitleComponent, TooltipComponent } from 'echarts/components' +import { useTranslation } from 'react-i18next' import { CanvasRenderer } from 'echarts/renderers' @@ -14,68 +15,68 @@ echarts.use([TitleComponent, TooltipComponent, PieChart, CanvasRenderer]) const truncate = (str, n) => str.length > n ? `${str.substr(0, n - 1)}...` : str -export default class RepresentativesWeightChart extends React.Component { - render() { - const { accounts, totalWeight, quorumTotal } = this.props +export default function RepresentativesWeightChart({ + accounts, + totalWeight, + quorumTotal +}) { + const { t } = useTranslation() + const denominator = quorumTotal || totalWeight - const denominator = quorumTotal || totalWeight + const weightData = [] + accounts.forEach((a) => { + const bn = BigNumber(a.account_meta.weight) + const weight = bn.shiftedBy(-30).toFixed(0) + const pct = bn.dividedBy(denominator).multipliedBy(100).toFixed(1) - const weightData = [] - accounts.forEach((a) => { - const bn = BigNumber(a.account_meta.weight) - const weight = bn.shiftedBy(-30).toFixed(0) - const pct = bn.dividedBy(denominator).multipliedBy(100).toFixed(1) + const label = a.alias || a.account + weightData.push([weight, label, pct]) + }) - const label = a.alias || a.account - weightData.push([weight, label, pct]) - }) - - const option = { - tooltip: { - className: 'echarts-tooltip', - trigger: 'item', - formatter: (p) => - `${p.data[1]}
${BigNumber(p.data[0]).toFormat(0)} (${ - p.data[2] - } %)` - }, - title: { - top: 10, - left: 'center', - text: 'Weight Distribution by Rep', - textStyle: { - fontWeight: 'normal', - fontFamily: 'IBM Plex Mono' - } - }, - series: [ - { - type: 'pie', - radius: '50%', - avoidLabelOverlap: false, - data: weightData.sort((a, b) => b[0] - a[0]), - label: { - bleedMargin: 30, - formatter: (p) => `${truncate(p.data[1], 20)}: ${p.data[2]} %` - }, - labelLayout: { - height: 50, - hideOverlap: true - } + const option = { + tooltip: { + className: 'echarts-tooltip', + trigger: 'item', + formatter: (p) => + `${p.data[1]}
${BigNumber(p.data[0]).toFormat(0)} (${p.data[2]} %)` + }, + title: { + top: 10, + left: 'center', + text: t( + 'representatives_weight_chart.title', + 'Weight Distribution by Representative' + ), + textStyle: { + fontWeight: 'normal', + fontFamily: 'IBM Plex Mono' + } + }, + series: [ + { + type: 'pie', + radius: '50%', + avoidLabelOverlap: false, + data: weightData.sort((a, b) => b[0] - a[0]), + label: { + bleedMargin: 30, + formatter: (p) => `${truncate(p.data[1], 20)}: ${p.data[2]} %` + }, + labelLayout: { + height: 50, + hideOverlap: true } - ] - } - - return ( - <> - - - ) + } + ] } + + return ( + + ) } RepresentativesWeightChart.propTypes = { diff --git a/src/views/components/representatives-weight/representatives-weight.js b/src/views/components/representatives-weight/representatives-weight.js index 0c9b4b89..53e6d30f 100644 --- a/src/views/components/representatives-weight/representatives-weight.js +++ b/src/views/components/representatives-weight/representatives-weight.js @@ -1,59 +1,62 @@ import React from 'react' import BigNumber from 'bignumber.js' import ImmutablePropTypes from 'react-immutable-proptypes' +import { useTranslation } from 'react-i18next' import './representatives-weight.styl' -export default class RepresentativesWeight extends React.Component { - render() { - const { network } = this.props - const onlineWeight = BigNumber( - network.getIn(['weight', 'onlineWeight', 'median'], 0) - ) - const trendedWeight = BigNumber( - network.getIn(['weight', 'trendedWeight', 'median'], 0) - ) - const quorumTotal = BigNumber.max(onlineWeight, trendedWeight) - const quorumWeightDelta = quorumTotal.multipliedBy(0.67) +export default function RepresentativesWeight({ network }) { + const { t } = useTranslation() + const online_weight = BigNumber( + network.getIn(['weight', 'onlineWeight', 'median'], 0) + ) + const trended_weight = BigNumber( + network.getIn(['weight', 'trendedWeight', 'median'], 0) + ) + const quorum_total = BigNumber.max(online_weight, trended_weight) + const quorum_weight_delta = quorum_total.multipliedBy(0.67) - const onlineSelected = onlineWeight.isGreaterThan(trendedWeight) + const online_selected = online_weight.isGreaterThan(trended_weight) - const onlineNano = onlineWeight.shiftedBy(-36) - const trendedNano = trendedWeight.shiftedBy(-36) - const quorumNano = quorumWeightDelta.shiftedBy(-36) - return ( -
-
-
-
Trended
-
- {trendedNano.isNaN() ? '-' : `${trendedNano.toFormat(1)}M`} -
+ const online_nano = online_weight.shiftedBy(-36) + const trended_nano = trended_weight.shiftedBy(-36) + const quorum_nano = quorum_weight_delta.shiftedBy(-36) + return ( +
+
+
+
+ {t('representatives_weight.trended', 'Trended')}
-
-
Online
-
- {onlineNano.isNaN() ? '-' : `${onlineNano.toFormat(1)}M`} -
+
+ {trended_nano.isNaN() ? '-' : `${trended_nano.toFormat(1)}M`}
-
-
- Quorum Delta -
-
- {quorumNano.isNaN() ? '-' : `${quorumNano.toFormat(1)}M`} -
+
+
+
+ {t('common.online', 'Online')} +
+
+ {online_nano.isNaN() ? '-' : `${online_nano.toFormat(1)}M`} +
+
+
+
+ {t('common.quorum_delta', 'Quorum Delta')} +
+
+ {quorum_nano.isNaN() ? '-' : `${quorum_nano.toFormat(1)}M`}
- ) - } +
+ ) } RepresentativesWeight.propTypes = { diff --git a/src/views/components/representatives/representatives.js b/src/views/components/representatives/representatives.js index 80a8b3e0..501fcbc3 100644 --- a/src/views/components/representatives/representatives.js +++ b/src/views/components/representatives/representatives.js @@ -6,18 +6,19 @@ import LinearProgress from '@mui/material/LinearProgress' import { DataGrid } from '@mui/x-data-grid' import BigNumber from 'bignumber.js' import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord' +import { useTranslation } from 'react-i18next' import Uptime from '@components/uptime' import { timeago } from '@core/utils' import './representatives.styl' -function bytesToSize(bytes) { +function bytesToSize({ bytes, t }) { const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'] if (bytes === 0) return { value: 0, - label: 'Unlimited' + label: t('common.unlimited', 'Unlimited') } const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10) @@ -63,237 +64,234 @@ function sort_comparator(a, b, cell_params_a) { } } -export default class Representatives extends React.Component { - render() { - const { - accounts, - totalWeight, - isLoading, - quorumTotal, - table_height = 600 - } = this.props +export default function Representatives({ + accounts, + totalWeight, + quorumTotal, + isLoading, + table_height = 600 +}) { + const { t } = useTranslation() + const denominator = quorumTotal || totalWeight - const denominator = quorumTotal || totalWeight - - const columns = [ - { - field: 'status', - headerName: '', - width: 20, - renderCell: (p) => , - valueGetter: (p) => p.row.is_online, - sortComparator: sort_comparator + const columns = [ + { + field: 'status', + headerName: '', + width: 20, + renderCell: (p) => , + valueGetter: (p) => p.row.is_online, + sortComparator: sort_comparator + }, + { + field: 'alias', + headerName: t('representatives.alias', 'Alias'), + width: 200, + sortComparator: sort_comparator + }, + { + field: 'account', + headerName: t('common.account', { count: 1, defaultValue: 'Account' }), + renderCell: (p) => {p.row.account}, + width: 160, + sortComparator: sort_comparator + }, + { + field: 'weight', + headerName: t('common.weight', 'Weight'), + width: 140, + valueFormatter: (p) => + p.value ? `${BigNumber(p.value).shiftedBy(-30).toFormat(0)}` : null, + valueGetter: (p) => p.row.account_meta.weight, + sortComparator: sort_comparator + }, + { + field: 'weight_pct', + headerName: '%', + width: 80, + valueFormatter: (p) => (p.value ? `${p.value.toFixed(2)}%` : null), + valueGetter: (p) => + p.row.account_meta.weight + ? BigNumber(p.row.account_meta.weight) + .dividedBy(denominator) + .multipliedBy(100) + : null, + sortComparator: sort_comparator + }, + { + field: 'confs_behind', + headerName: t('common.confirmations_behind', 'Confs Behind'), + width: 145, + valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), + valueGetter: (p) => p.row.telemetry.cemented_behind, + sortComparator: sort_comparator + }, + { + field: 'uptime', + headerName: t('common.uptime', 'Uptime'), + width: 150, + renderCell: (p) => ( + + ), + valueGetter: (p) => (p.row.last_online || 0) - (p.row.last_offline || 0), + sortComparator: sort_comparator + }, + { + field: 'version', + headerName: t('common.version', 'Version'), + width: 110, + valueGetter: (p) => p.row.version, + sortComparator: sort_comparator + }, + { + field: 'bandwidth_cap', + headerName: t('common.bandwidth_limit_short', 'BW Limit'), + width: 120, + valueFormatter: (p) => { + if (p.api.getRow(p.id).telemetry.bandwidth_cap === 0) + return t('common.unlimited', 'Unlimited') + return p.api.getRow(p.id).telemetry.bandwidth_cap + ? bytesToSize({ + bytes: p.api.getRow(p.id).telemetry.bandwidth_cap, + t + }).label + : null }, - { - field: 'alias', - headerName: 'Alias', - width: 200, - sortComparator: sort_comparator + valueGetter: (p) => { + if (p.row.telemetry.bandwidth_cap === 0) return Infinity + return p.row.telemetry.bandwidth_cap + ? bytesToSize({ bytes: p.row.telemetry.bandwidth_cap, t }).value + : null }, - { - field: 'account', - headerName: 'Account', - renderCell: (p) => ( - {p.row.account} + sortComparator: sort_comparator + }, + { + field: 'peer_count', + headerName: t('common.peers', 'Peers'), + width: 100, + valueGetter: (p) => p.row.telemetry.peer_count, + sortComparator: sort_comparator + }, + { + field: 'port', + headerName: t('common.port', 'Port'), + valueGetter: (p) => p.row.telemetry.port, + sortComparator: sort_comparator + }, + { + field: 'blocks_behind', + headerName: t('common.blocks_behind', 'Blocks Behind'), + width: 145, + valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), + valueGetter: (p) => p.row.telemetry.block_behind, + sortComparator: sort_comparator + }, + { + field: 'cemented_count', + headerName: t('common.conf_short', 'Conf.'), + width: 140, + valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), + valueGetter: (p) => p.row.telemetry.cemented_count, + sortComparator: sort_comparator + }, + { + field: 'block_count', + headerName: t('common.blocks', 'Blocks'), + width: 140, + valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), + valueGetter: (p) => p.row.telemetry.block_count, + sortComparator: sort_comparator + }, + { + field: 'unchecked_count', + headerName: t('common.unchecked_count', 'Unchecked'), + width: 140, + valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), + valueGetter: (p) => p.row.telemetry.unchecked_count, + sortComparator: sort_comparator + }, + { + field: 'cpu_cores', + headerName: t('representatives.cpu_cores', 'CPU Cores'), + width: 130, + valueGetter: (p) => p.row.representative_meta.cpu_cores, + sortComparator: sort_comparator + }, + { + field: 'cpu_model', + hide: true, + headerName: t('representatives.cpu_model', 'CPU Model'), + valueGetter: (p) => p.row.representative_meta.cpu_model, + sortComparator: sort_comparator + }, + { + field: 'watt_hour', + width: 120, + headerName: t('representatives.tdp', 'TDP (wH)'), + sortComparator: sort_comparator + }, + { + field: 'protocol_version', + headerName: t('representatives.protocol_version', 'Protocol'), + width: 110, + valueGetter: (p) => p.row.telemetry.protocol_version, + sortComparator: sort_comparator + }, + { + field: 'last_seen', + width: 130, + headerName: t('representatives.last_seen', 'Last Seen'), + renderCell: (p) => + p.row.is_online ? ( + + ) : ( + timeago.format(p.row.last_seen * 1000, 'nano_short') ), - width: 160, - sortComparator: sort_comparator - }, - { - field: 'weight', - headerName: 'Weight', - width: 140, - valueFormatter: (p) => - p.value ? `${BigNumber(p.value).shiftedBy(-30).toFormat(0)}` : null, - valueGetter: (p) => p.row.account_meta.weight, - sortComparator: sort_comparator - }, - { - field: 'weight_pct', - headerName: '%', - width: 80, - valueFormatter: (p) => (p.value ? `${p.value.toFixed(2)}%` : null), - valueGetter: (p) => - p.row.account_meta.weight - ? BigNumber(p.row.account_meta.weight) - .dividedBy(denominator) - .multipliedBy(100) - : null, - sortComparator: sort_comparator - }, - { - field: 'confs_behind', - headerName: 'Confs Behind', - width: 145, - valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), - valueGetter: (p) => p.row.telemetry.cemented_behind, - sortComparator: sort_comparator - }, - { - field: 'uptime', - headerName: 'Uptime', - width: 150, - renderCell: (p) => ( - - ), - valueGetter: (p) => - (p.row.last_online || 0) - (p.row.last_offline || 0), - sortComparator: sort_comparator - }, - { - field: 'version', - headerName: 'Version', - width: 110, - valueGetter: (p) => p.row.version, - sortComparator: sort_comparator - }, - { - field: 'bandwidth_cap', - headerName: 'BW Limit', - width: 120, - valueFormatter: (p) => { - if (p.api.getRow(p.id).telemetry.bandwidth_cap === 0) - return 'Unlimited' - return p.api.getRow(p.id).telemetry.bandwidth_cap - ? bytesToSize(p.api.getRow(p.id).telemetry.bandwidth_cap).label - : null - }, - valueGetter: (p) => { - if (p.row.telemetry.bandwidth_cap === 0) return Infinity - return p.row.telemetry.bandwidth_cap - ? bytesToSize(p.row.telemetry.bandwidth_cap).value - : null - }, - sortComparator: sort_comparator - }, - { - field: 'peer_count', - headerName: 'Peers', - width: 100, - valueGetter: (p) => p.row.telemetry.peer_count, - sortComparator: sort_comparator - }, - { - field: 'port', - headerName: 'Port', - valueGetter: (p) => p.row.telemetry.port, - sortComparator: sort_comparator - }, - { - field: 'blocks_behind', - headerName: 'Blocks Behind', - width: 145, - valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), - valueGetter: (p) => p.row.telemetry.block_behind, - sortComparator: sort_comparator - }, - { - field: 'cemented_count', - headerName: 'Confs.', - width: 140, - valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), - valueGetter: (p) => p.row.telemetry.cemented_count, - sortComparator: sort_comparator - }, - { - field: 'block_count', - headerName: 'Blocks', - width: 140, - valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), - valueGetter: (p) => p.row.telemetry.block_count, - sortComparator: sort_comparator - }, - { - field: 'unchecked_count', - headerName: 'Unchecked', - width: 140, - valueFormatter: (p) => (p.value ? BigNumber(p.value).toFormat() : null), - valueGetter: (p) => p.row.telemetry.unchecked_count, - sortComparator: sort_comparator - }, - { - field: 'cpu_cores', - headerName: 'CPU Cores', - width: 130, - valueGetter: (p) => p.row.representative_meta.cpu_cores, - sortComparator: sort_comparator - }, - { - field: 'cpu_model', - hide: true, - headerName: 'CPU Model', - valueGetter: (p) => p.row.representative_meta.cpu_model, - sortComparator: sort_comparator - }, - { - field: 'watt_hour', - width: 120, - headerName: 'TDP (wH)', - sortComparator: sort_comparator - }, - { - field: 'protocol_version', - headerName: 'Protocol', - width: 110, - valueGetter: (p) => p.row.telemetry.protocol_version, - sortComparator: sort_comparator - }, - { - field: 'last_seen', - width: 130, - headerName: 'Last Seen', - renderCell: (p) => - p.row.is_online ? ( - - ) : ( - timeago.format(p.row.last_seen * 1000, 'nano_short') - ), - valueGetter: (p) => Math.floor(Date.now() / 1000) - p.row.last_seen, - sortComparator: sort_comparator - }, - { - field: 'asname', - headerName: 'Host ASN', - width: 130, - valueGetter: (p) => p.row.network.asname, - sortComparator: sort_comparator - }, - { - field: 'country', - headerName: 'Country', - width: 130, - valueGetter: (p) => p.row.network.country, - sortComparator: sort_comparator - }, - { - field: 'address', - headerName: 'Address', - width: 320, - valueGetter: (p) => p.row.telemetry.address, - sortComparator: sort_comparator - } - ] - return ( -
- row.account} - rows={accounts.toJS()} - initialState={{ - sorting: { - sortModel: [{ field: 'weight', sort: 'desc' }] - } - }} - /> -
- ) - } + valueGetter: (p) => Math.floor(Date.now() / 1000) - p.row.last_seen, + sortComparator: sort_comparator + }, + { + field: 'asname', + headerName: t('representatives.host_asn', 'Host ASN'), + width: 130, + valueGetter: (p) => p.row.network.asname, + sortComparator: sort_comparator + }, + { + field: 'country', + headerName: t('common.country', 'Country'), + width: 130, + valueGetter: (p) => p.row.network.country, + sortComparator: sort_comparator + }, + { + field: 'address', + headerName: t('common.address', 'Address'), + width: 320, + valueGetter: (p) => p.row.telemetry.address, + sortComparator: sort_comparator + } + ] + return ( +
+ row.account} + rows={accounts.toJS()} + initialState={{ + sorting: { + sortModel: [{ field: 'weight', sort: 'desc' }] + } + }} + /> +
+ ) } Representatives.propTypes = { diff --git a/src/views/components/search-bar/search-bar.js b/src/views/components/search-bar/search-bar.js index 78d47024..79e91319 100644 --- a/src/views/components/search-bar/search-bar.js +++ b/src/views/components/search-bar/search-bar.js @@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react' import KeyboardCommandKeyIcon from '@mui/icons-material/KeyboardCommandKey' import ClearIcon from '@mui/icons-material/Clear' import SearchIcon from '@mui/icons-material/Search' +import { useTranslation } from 'react-i18next' import history from '@core/history' @@ -11,6 +12,7 @@ const ACCOUNT_REGEX = /((nano|xrb)_)?[13][13-9a-km-uw-z]{59}/ const BLOCK_REGEX = /[0-9A-F]{64}/ const SearchBar = () => { + const { t } = useTranslation() const [value, setValue] = useState('') const [invalid, setInvalid] = useState(false) const input_ref = useRef(null) @@ -52,7 +54,10 @@ const SearchBar = () => { ref={input_ref} className={`search__input ${is_filled ? 'filled' : ''}`} type='text' - placeholder='Search by Address / Block Hash' + placeholder={t( + 'search_bar.placeholder', + 'Search by Address / Block Hash' + )} value={value} onChange={handle_change} /> diff --git a/src/views/components/uptime/uptime.js b/src/views/components/uptime/uptime.js index a774b6a1..2b7af79d 100644 --- a/src/views/components/uptime/uptime.js +++ b/src/views/components/uptime/uptime.js @@ -1,54 +1,54 @@ import React from 'react' import PropTypes from 'prop-types' +import { useTranslation } from 'react-i18next' import './uptime.styl' const online = '#3bd671' const offline = '#ee6666' -export default class Uptime extends React.Component { - render() { - const { data, length, expanded } = this.props - - const ticks = [] - const sliced = length ? data.slice(0, length) : data - const height = expanded ? 18 : 14 - const width = expanded ? 4 : 3 - const spacing = expanded ? 4 : 2 - sliced.forEach((d, key) => - ticks.push( - - ) +export default function Uptime({ data, length, expanded }) { + const { t } = useTranslation() + const ticks = [] + const sliced = length ? data.slice(0, length) : data + const height = expanded ? 18 : 14 + const width = expanded ? 4 : 3 + const spacing = expanded ? 4 : 2 + sliced.forEach((d, key) => + ticks.push( + ) + ) - return ( -
- - {ticks} - - {Boolean(expanded) && ( -
-
Now
-
- {Math.round((sliced[sliced.length - 1].interval * 2) / 24)} days - ago -
+ return ( +
+ + {ticks} + + {Boolean(expanded) && ( +
+
{t('uptime.now', 'Now')}
+
+ {`${Math.round((sliced[sliced.length - 1].interval * 2) / 24)} ${t( + 'uptime.days_ago', + 'days ago' + )}`}
- )} -
- ) - } +
+ )} +
+ ) } Uptime.propTypes = { diff --git a/src/views/pages/account/account.js b/src/views/pages/account/account.js index 4bd77464..b7e36688 100644 --- a/src/views/pages/account/account.js +++ b/src/views/pages/account/account.js @@ -10,6 +10,7 @@ import FilterNoneIcon from '@mui/icons-material/FilterNone' import IconButton from '@mui/material/IconButton' import copy from 'copy-text-to-clipboard' import Tooltip from '@mui/material/Tooltip' +import { useTranslation } from 'react-i18next' import RepresentativeTelemetryChart from '@components/representative-telemetry-chart' import RepresentativeDelegators from '@components/representative-delegators' @@ -28,9 +29,7 @@ import Menu from '@components/menu' import './account.styl' -function TabPanel(props) { - const { children, value, index, ...other } = props - +function TabPanel({ children, value, index, ...other }) { return (