From faf397f6813737cdc986a2ff5d94a795c937c161 Mon Sep 17 00:00:00 2001 From: martbost Date: Fri, 21 Aug 2026 07:23:55 -0500 Subject: [PATCH] Add on-site translation for multilingual members Floating translate button (bottom-left) on every member-facing page lazy-loads the Google Translate element; language choice persists across pages via the googtrans cookie. CSP extended for Google's translate hosts only. Chatbot now replies in the member's language and a canned answer points at the button. --- private/join-now.html | 2 +- public/chat.js | 2 ++ public/contract.html | 2 +- public/disclaimer.html | 2 +- public/how-pay-works.html | 2 +- public/index.html | 2 +- public/join.html | 2 +- public/my.html | 2 +- public/start.html | 2 +- public/tools.html | 2 +- public/training.html | 2 +- public/translate.js | 47 +++++++++++++++++++++++++++++++++++++++ server.js | 3 ++- 13 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 public/translate.js diff --git a/private/join-now.html b/private/join-now.html index e8724dd..0992066 100644 --- a/private/join-now.html +++ b/private/join-now.html @@ -67,4 +67,4 @@

No income is guaranteed. Cryptocurrency and smart-contract participation carry risk. Only use funds you can afford to lose.

- + diff --git a/public/chat.js b/public/chat.js index 1448a30..25ce28e 100644 --- a/public/chat.js +++ b/public/chat.js @@ -34,6 +34,8 @@ a:()=>`Great question — and we checked it on-chain, not just in theory. The contract needs no one to keep it running: joins, upgrades, placement and every payout are fully automatic — no button anyone has to press, no expiry. If the creators walked away, lost their keys, or vanished, member payments keep flowing exactly as coded. We also verified that the founder, development and fee wallets are ordinary wallets, not programs — an ordinary wallet always accepts an incoming payment even if its key is lost forever, so a dead admin wallet can't jam a single member payment (at worst the project's own fee sits there uncollected). And the contract holds no stored balance — every payment is delivered in the same transaction. Full write-up in section 6 of rmcircle.team/contract.`}, {k:['pyramid','ponzi','pyramid scheme','ponzi scheme','mlm','recruiting scheme','is this a scheme'], a:()=>`A pyramid or Ponzi scheme funnels everyone's money to a central company and pays earlier joiners out of later joiners' deposits — and you can't verify any of it. This is the opposite: no company holds the money. A public smart contract on Polygon sends each payment person-to-person in the same transaction it arrives, and you can read the code and every payout yourself on-chain — nothing pooled, nothing hidden, rules that can't be changed. It is a team build, so it takes real effort and carries real crypto risk — not a passive investment. But you don't have to trust anyone; verify it at rmcircle.team/contract. No income is guaranteed.`}, + {k:['translate','translation','language','español','espanol','spanish','french','portuguese','not in english','other language'], + a:()=>`Tap the 🌐 Translate button in the bottom-left corner of any page — pick your language once and every page stays translated while you browse. Your phone's browser also usually offers its own "Translate page" option. And you can type to me here in ANY language — I'll answer in yours.`}, {k:['how many people','team size','organization size','org size','how big is my team','total team','people in my team','members below'], a:()=>`Open your dashboard at rmcircle.team/my and look at the top of the "Your team" panel — the organization bar shows your total member count, how many generations deep your team runs, how many positions below you are qualified, the total POL earned below you, and its approximate US-dollar value at the latest POL price (refreshed about hourly). The matrix cards under it break the same numbers down leg by leg (the ⬇ rollup line on each card counts everyone underneath, all the way down).`}, {k:['wont upgrade',"won't upgrade",'not upgrading','refuses to upgrade','stalled','stuck member','not ready to upgrade','below me wont','waiting on someone','blocked by'], diff --git a/public/contract.html b/public/contract.html index 371ecd7..a65d51f 100644 --- a/public/contract.html +++ b/public/contract.html @@ -30,4 +30,4 @@ - + diff --git a/public/disclaimer.html b/public/disclaimer.html index 640ddd9..e0192ed 100644 --- a/public/disclaimer.html +++ b/public/disclaimer.html @@ -25,4 +25,4 @@ - + diff --git a/public/how-pay-works.html b/public/how-pay-works.html index f5dc75a..5141c61 100644 --- a/public/how-pay-works.html +++ b/public/how-pay-works.html @@ -74,4 +74,4 @@ - + diff --git a/public/index.html b/public/index.html index 05c5292..23cdacc 100644 --- a/public/index.html +++ b/public/index.html @@ -21,4 +21,4 @@
Ready to start?

See the current team placement.

The onboarding page automatically shows the sponsor position the team is currently helping. Always use the sponsor shown there instead of an old screenshot or saved link.

Open Getting Started Instructions →
- + diff --git a/public/join.html b/public/join.html index 383aded..d77a3a3 100644 --- a/public/join.html +++ b/public/join.html @@ -27,4 +27,4 @@
Risk reminder: participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.
- + diff --git a/public/my.html b/public/my.html index 848d5db..2ac5e10 100644 --- a/public/my.html +++ b/public/my.html @@ -31,4 +31,4 @@ - + diff --git a/public/start.html b/public/start.html index 19f4def..98e861c 100644 --- a/public/start.html +++ b/public/start.html @@ -16,4 +16,4 @@
Risk reminder: participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.
RM Circle Premium Team Build Roadmap — core strategy, step-by-step guide, premium levels, and duplication formula
This roadmap is the plan every member follows — tap to view full size.
- + diff --git a/public/tools.html b/public/tools.html index 5cbe649..98e32d6 100644 --- a/public/tools.html +++ b/public/tools.html @@ -356,4 +356,4 @@ Watch the short training, look at the live payment feed, then ask me anything. - + diff --git a/public/training.html b/public/training.html index 01892a1..58c1fd0 100644 --- a/public/training.html +++ b/public/training.html @@ -35,4 +35,4 @@ - + diff --git a/public/translate.js b/public/translate.js new file mode 100644 index 0000000..6531a3a --- /dev/null +++ b/public/translate.js @@ -0,0 +1,47 @@ +// Floating language picker — lazy-loads the Google Translate element on first +// tap so pages pay zero cost until someone actually wants a translation. The +// googtrans cookie carries the chosen language across every page after that. +(function(){ + var STYLE = ''+ + '#rmcTrBtn{position:fixed;bottom:18px;left:18px;z-index:9998;display:flex;align-items:center;gap:7px;'+ + 'background:#0d2236;border:1px solid #24425d;color:#f7f9fc;border-radius:999px;padding:9px 14px;'+ + 'font:700 13px/1 Inter,system-ui,sans-serif;cursor:pointer;box-shadow:0 6px 24px rgba(0,0,0,.35)}'+ + '#rmcTrBtn:hover{border-color:#4ed6cb}'+ + '#rmcTrPanel{position:fixed;bottom:64px;left:18px;z-index:9999;background:#0d2236;border:1px solid #24425d;'+ + 'border-radius:14px;padding:14px;display:none;box-shadow:0 10px 34px rgba(0,0,0,.45)}'+ + '#rmcTrPanel.on{display:block}'+ + '#rmcTrPanel .t{color:#aebdca;font:600 12px/1.4 Inter,system-ui,sans-serif;margin:0 0 8px}'+ + /* suppress Google's top banner + body shift */ + '.goog-te-banner-frame,.skiptranslate iframe{display:none!important}'+ + 'body{top:0!important}'+ + '#google_translate_element select{background:#071726;color:#f7f9fc;border:1px solid #24425d;border-radius:8px;padding:8px;font-size:14px;max-width:230px}'+ + '#google_translate_element .goog-te-gadget{color:#aebdca;font-size:11px}'+ + '#google_translate_element .goog-logo-link{color:#aebdca!important}'; + var loaded=false; + function mount(){ + var st=document.createElement('style');st.textContent=STYLE;document.head.appendChild(st); + var btn=document.createElement('button');btn.id='rmcTrBtn';btn.type='button'; + btn.innerHTML='🌐 Translate'; + btn.setAttribute('aria-label','Translate this page'); + var panel=document.createElement('div');panel.id='rmcTrPanel'; + panel.innerHTML='

Choose your language — it sticks on every page.

'; + document.body.appendChild(btn);document.body.appendChild(panel); + btn.addEventListener('click',function(){ + panel.classList.toggle('on'); + if(!loaded){ + loaded=true; + window.googleTranslateElementInit=function(){ + new google.translate.TranslateElement({pageLanguage:'en',autoDisplay:false},'google_translate_element'); + }; + var s=document.createElement('script'); + s.src='https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit'; + s.onerror=function(){document.getElementById('google_translate_element').innerHTML='

Translation is unavailable right now — your browser’s own “Translate page” option also works on this site.

';}; + document.head.appendChild(s); + } + }); + document.addEventListener('click',function(e){ + if(panel.classList.contains('on')&&!panel.contains(e.target)&&e.target!==btn&&!btn.contains(e.target))panel.classList.remove('on'); + }); + } + if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',mount);else mount(); +})(); diff --git a/server.js b/server.js index e761dad..f400eb0 100644 --- a/server.js +++ b/server.js @@ -50,6 +50,7 @@ FACTS: - UPGRADING FROM THE DASHBOARD: a qualified member can upgrade their level directly on their dashboard (rmcircle.team/my/) — an "Upgrade" card appears with the exact next-level cost read live from the contract; they connect the wallet that OWNS the position, confirm one transaction, done. The site never touches the funds (wallet pays the contract directly). If the wallet doesn't cover the cost, the card offers the MoonPay card-buy option. On phones, open the page inside the wallet app's browser. - MESSAGES (on-site, wallet-verified): every member dashboard has a Messages panel — sign in once with the wallet that owns your position (a free signature, cannot move funds), then message your upline or anyone in your own team, or broadcast to your whole team. Spam-proof by design: messaging only works along your own matrix lines, so strangers can't message you. Unread messages show as a bell on your dashboard. Members are told the team admin can review messages for abuse. No email address needed. - BUYING POL WITH A CARD (for people brand new to crypto): the site links to MoonPay (moonpay.com/buy/pol) on the training page, the start page, and automatically on the join page when a connected wallet's balance is short. Guidance to give: choose POL on the POLYGON network, send it to YOUR OWN wallet address, buy about entry + gas (~385 POL). MoonPay is an independent company (merchant of record) — it handles ID verification and charges its own card fee (~4.5%); this site never touches or holds anyone's money. First purchases can take a few minutes to arrive. +- LANGUAGE: always reply in the language the member writes in — translate program terms naturally and keep level names (Scintilla, Ascensus, ...) as-is. Site pages have a floating 🌐 Translate button (bottom-left) that machine-translates any page and remembers the choice. - COACHING DOCTRINE (teach forward): whenever you give a member guidance about helping their team, frame it so they learn to run the same play for their own two — e.g. "do X, then show your two how to spot this on THEIR dashboard's Coach Your Team panel." The goal is never just fixing one member's next step; it is teaching people how to teach. Every member's dashboard has the same Coach Your Team panel, so the play duplicates at every depth. - Telegram group for live team help: ${c.telegramUrl || 'https://t.me/cryptoteambuild'} - OBJECTIONS (answer honestly, never with hype or promises): @@ -354,7 +355,7 @@ function publicSponsorPayload(sponsor, config) { if(!sponsor)return null; return {id:sponsor.id,name:config.showSponsorName?sponsor.name:null,directs:sponsor.directs,goal:2,level:sponsor.level,referralUrl:`${config.dappReferralBaseUrl}${encodeURIComponent(sponsor.id)}`}; } -const CSP_BASE="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:; form-action 'self'; frame-src https://www.youtube-nocookie.com"; +const CSP_BASE="default-src 'self'; script-src 'self' https://translate.google.com https://translate.googleapis.com https://translate-pa.googleapis.com; style-src 'self' 'unsafe-inline' https://www.gstatic.com; img-src 'self' data: https://www.gstatic.com https://fonts.gstatic.com https://www.google.com https://translate.googleapis.com; connect-src 'self' https://translate.googleapis.com https://translate-pa.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; form-action 'self'; frame-src https://www.youtube-nocookie.com https://translate.google.com"; function securityHeaders(extra={}) { // Public pages must render inside safelist / traffic-exchange iframes, so framing stays open here; admin.html re-locks it via ADMIN_FRAME_HEADERS. return {