mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Start localization
Trac 30310
This commit is contained in:
parent
f94ef87c46
commit
4e5a50f2b5
9 changed files with 115 additions and 26 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,5 +19,6 @@ proxy/webext/popup.js
|
||||||
proxy/webext/embed.html
|
proxy/webext/embed.html
|
||||||
proxy/webext/embed.css
|
proxy/webext/embed.css
|
||||||
proxy/webext/assets/
|
proxy/webext/assets/
|
||||||
|
proxy/webext/_locales/
|
||||||
ignore/
|
ignore/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|
|
@ -4,6 +4,20 @@
|
||||||
UI
|
UI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class Messages {
|
||||||
|
constructor(json) {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
getMessage(m, ...rest) {
|
||||||
|
let message = this.json[m].message;
|
||||||
|
return message.replace(/\$(\d+)/g, (...args) => {
|
||||||
|
return rest[Number(args[1]) - 1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let messages = null;
|
||||||
|
|
||||||
class BadgeUI extends UI {
|
class BadgeUI extends UI {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -16,7 +30,7 @@ class BadgeUI extends UI {
|
||||||
missingFeature(missing) {
|
missingFeature(missing) {
|
||||||
this.popup.setEnabled(false);
|
this.popup.setEnabled(false);
|
||||||
this.popup.setActive(false);
|
this.popup.setActive(false);
|
||||||
this.popup.setStatusText("Snowflake is off");
|
this.popup.setStatusText(messages.getMessage('popupStatusOff'));
|
||||||
this.popup.setStatusDesc(missing, true);
|
this.popup.setStatusDesc(missing, true);
|
||||||
this.popup.hideButton();
|
this.popup.hideButton();
|
||||||
}
|
}
|
||||||
|
@ -24,20 +38,23 @@ class BadgeUI extends UI {
|
||||||
turnOn() {
|
turnOn() {
|
||||||
const clients = this.active ? 1 : 0;
|
const clients = this.active ? 1 : 0;
|
||||||
this.popup.setChecked(true);
|
this.popup.setChecked(true);
|
||||||
this.popup.setToggleText('Turn Off');
|
this.popup.setToggleText(messages.getMessage('popupTurnOff'));
|
||||||
this.popup.setStatusText(`${clients} client${(clients !== 1) ? 's' : ''} connected.`);
|
if (clients > 0) {
|
||||||
|
this.popup.setStatusText(messages.getMessage('popupStatusOn', String(clients)));
|
||||||
|
} else {
|
||||||
|
this.popup.setStatusText(messages.getMessage('popupStatusReady'));
|
||||||
|
}
|
||||||
// FIXME: Share stats from webext
|
// FIXME: Share stats from webext
|
||||||
const total = 0;
|
this.popup.setStatusDesc('');
|
||||||
this.popup.setStatusDesc(`Your snowflake has helped ${total} user${(total !== 1) ? 's' : ''} circumvent censorship in the last 24 hours.`);
|
|
||||||
this.popup.setEnabled(true);
|
this.popup.setEnabled(true);
|
||||||
this.popup.setActive(this.active);
|
this.popup.setActive(this.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
turnOff() {
|
turnOff() {
|
||||||
this.popup.setChecked(false);
|
this.popup.setChecked(false);
|
||||||
this.popup.setToggleText('Turn On');
|
this.popup.setToggleText(messages.getMessage('popupTurnOn'));
|
||||||
this.popup.setStatusText("Snowflake is off");
|
this.popup.setStatusText(messages.getMessage('popupStatusOff'));
|
||||||
this.popup.setStatusDesc("");
|
this.popup.setStatusDesc('');
|
||||||
this.popup.setEnabled(false);
|
this.popup.setEnabled(false);
|
||||||
this.popup.setActive(false);
|
this.popup.setActive(false);
|
||||||
}
|
}
|
||||||
|
@ -108,12 +125,12 @@ var debug, snowflake, config, broker, ui, log, dbg, init, update, silenceNotific
|
||||||
ui = new BadgeUI();
|
ui = new BadgeUI();
|
||||||
|
|
||||||
if (!Util.hasWebRTC()) {
|
if (!Util.hasWebRTC()) {
|
||||||
ui.missingFeature("WebRTC feature is not detected.");
|
ui.missingFeature(messages.getMessage('popupWebRTCOff'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Util.hasCookies()) {
|
if (!Util.hasCookies()) {
|
||||||
ui.missingFeature("Cookies are not enabled.");
|
ui.missingFeature(messages.getMessage('badgeCookiesOff'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +170,20 @@ var debug, snowflake, config, broker, ui, log, dbg, init, update, silenceNotific
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onload = init;
|
window.onload = function() {
|
||||||
|
const lang = 'en_US';
|
||||||
|
fetch(`./_locales/${lang}/messages.json`)
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) { return; }
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
messages = new Messages(json);
|
||||||
|
Popup.fill(document.body, (m) => {
|
||||||
|
return messages.getMessage(m);
|
||||||
|
});
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
|
@ -32,7 +32,8 @@ var SHARED_FILES = [
|
||||||
'embed.html',
|
'embed.html',
|
||||||
'embed.css',
|
'embed.css',
|
||||||
'popup.js',
|
'popup.js',
|
||||||
'assets'
|
'assets',
|
||||||
|
'_locales',
|
||||||
];
|
];
|
||||||
|
|
||||||
var concatJS = function(outDir, init, outFile) {
|
var concatJS = function(outDir, init, outFile) {
|
||||||
|
@ -67,7 +68,7 @@ task('test', 'snowflake unit tests', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
task('build', 'build the snowflake proxy', function() {
|
task('build', 'build the snowflake proxy', function() {
|
||||||
execSync('rm -r build');
|
execSync('rm -rf build');
|
||||||
execSync('cp -r ' + STATIC + '/ build/');
|
execSync('cp -r ' + STATIC + '/ build/');
|
||||||
concatJS('build', 'badge', 'embed.js');
|
concatJS('build', 'badge', 'embed.js');
|
||||||
console.log('Snowflake prepared.');
|
console.log('Snowflake prepared.');
|
||||||
|
@ -87,7 +88,7 @@ task('node', 'build the node binary', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
task('clean', 'remove all built files', function() {
|
task('clean', 'remove all built files', function() {
|
||||||
execSync('rm -r build test spec/support');
|
execSync('rm -rf build test spec/support');
|
||||||
});
|
});
|
||||||
|
|
||||||
var cmd = process.argv[2];
|
var cmd = process.argv[2];
|
||||||
|
|
32
proxy/static/_locales/en_US/messages.json
Normal file
32
proxy/static/_locales/en_US/messages.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"appDesc": {
|
||||||
|
"message": "Snowflake is a WebRTC pluggable transport for Tor."
|
||||||
|
},
|
||||||
|
"popupTurnOn": {
|
||||||
|
"message": "Turn On"
|
||||||
|
},
|
||||||
|
"popupTurnOff": {
|
||||||
|
"message": "Turn Off"
|
||||||
|
},
|
||||||
|
"popupLearnMore": {
|
||||||
|
"message": "Learn more"
|
||||||
|
},
|
||||||
|
"popupStatusOff": {
|
||||||
|
"message": "Snowflake is off"
|
||||||
|
},
|
||||||
|
"popupStatusOn": {
|
||||||
|
"message": "Number of users currently connected: $1"
|
||||||
|
},
|
||||||
|
"popupStatusReady": {
|
||||||
|
"message": "Your Snowflake is ready to help users circumvent censorship!"
|
||||||
|
},
|
||||||
|
"popupWebRTCOff": {
|
||||||
|
"message": "WebRTC feature is not detected."
|
||||||
|
},
|
||||||
|
"popupDescOn": {
|
||||||
|
"message": "Number of users your Snowflake has helped circumvent censorship in the last 24 hours: $1"
|
||||||
|
},
|
||||||
|
"badgeCookiesOff": {
|
||||||
|
"message": "Cookies are not enabled."
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,18 +11,18 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="active">
|
<div id="active">
|
||||||
<div id="statusimg"></div>
|
<div id="statusimg"></div>
|
||||||
<p id="statustext">Snowflake is off</p>
|
<p id="statustext">__MSG_popupStatusOff__</p>
|
||||||
<p id="statusdesc"></p>
|
<p id="statusdesc"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="b button">
|
<div class="b button">
|
||||||
<label id="toggle" for="enabled">Turn On</label>
|
<label id="toggle" for="enabled">__MSG_popupTurnOn__</label>
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
<input id="enabled" type="checkbox" />
|
<input id="enabled" type="checkbox" />
|
||||||
<span class="slider round"></span>
|
<span class="slider round"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="b learn">
|
<div class="b learn">
|
||||||
<a target="_blank" href="https://snowflake.torproject.org/">Learn more</a>
|
<a target="_blank" href="https://snowflake.torproject.org/">__MSG_popupLearnMore__</a>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
|
|
||||||
<p>Which looks like this:</p>
|
<p>Which looks like this:</p>
|
||||||
|
|
||||||
<iframe src="embed.html" width="320px" height="200px" frameborder="0" scrolling="no"></iframe>
|
<iframe src="embed.html" width="320px" height="240px" frameborder="0" scrolling="no"></iframe>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,4 +38,16 @@ class Popup {
|
||||||
setToggleText(txt) {
|
setToggleText(txt) {
|
||||||
document.getElementById('toggle').innerText = txt;
|
document.getElementById('toggle').innerText = txt;
|
||||||
}
|
}
|
||||||
|
static fill(n, func) {
|
||||||
|
switch(n.nodeType) {
|
||||||
|
case 3: { // Node.TEXT_NODE
|
||||||
|
const m = /^__MSG_([^_]*)__$/.exec(n.nodeValue);
|
||||||
|
if (m) { n.nodeValue = func(m[1]); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // Node.ELEMENT_NODE
|
||||||
|
n.childNodes.forEach(c => Popup.fill(c, func));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
/* global chrome, Popup */
|
/* global chrome, Popup */
|
||||||
|
|
||||||
|
// Fill i18n in HTML
|
||||||
|
window.onload = () => {
|
||||||
|
Popup.fill(document.body, (m) => {
|
||||||
|
return chrome.i18n.getMessage(m);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const port = chrome.runtime.connect({
|
const port = chrome.runtime.connect({
|
||||||
name: "popup"
|
name: "popup"
|
||||||
});
|
});
|
||||||
|
@ -11,8 +18,8 @@ port.onMessage.addListener((m) => {
|
||||||
if (missingFeature) {
|
if (missingFeature) {
|
||||||
popup.setEnabled(false);
|
popup.setEnabled(false);
|
||||||
popup.setActive(false);
|
popup.setActive(false);
|
||||||
popup.setStatusText("Snowflake is off");
|
popup.setStatusText(chrome.i18n.getMessage('popupStatusOff'));
|
||||||
popup.setStatusDesc("WebRTC feature is not detected.", true);
|
popup.setStatusDesc(chrome.i18n.getMessage('popupWebRTCOff'), true);
|
||||||
popup.hideButton();
|
popup.hideButton();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -21,13 +28,17 @@ port.onMessage.addListener((m) => {
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
popup.setChecked(true);
|
popup.setChecked(true);
|
||||||
popup.setToggleText('Turn Off');
|
popup.setToggleText(chrome.i18n.getMessage('popupTurnOff'));
|
||||||
popup.setStatusText(`${clients} client${(clients !== 1) ? 's' : ''} connected.`);
|
if (clients > 0) {
|
||||||
popup.setStatusDesc(`Your snowflake has helped ${total} user${(total !== 1) ? 's' : ''} circumvent censorship in the last 24 hours.`);
|
popup.setStatusText(chrome.i18n.getMessage('popupStatusOn', String(clients)));
|
||||||
|
} else {
|
||||||
|
popup.setStatusText(chrome.i18n.getMessage('popupStatusReady'));
|
||||||
|
}
|
||||||
|
popup.setStatusDesc((total > 0) ? chrome.i18n.getMessage('popupDescOn', String(total)) : '');
|
||||||
} else {
|
} else {
|
||||||
popup.setChecked(false);
|
popup.setChecked(false);
|
||||||
popup.setToggleText('Turn On');
|
popup.setToggleText(chrome.i18n.getMessage('popupTurnOn'));
|
||||||
popup.setStatusText("Snowflake is off");
|
popup.setStatusText(chrome.i18n.getMessage('popupStatusOff'));
|
||||||
popup.setStatusDesc("");
|
popup.setStatusDesc("");
|
||||||
}
|
}
|
||||||
popup.setEnabled(enabled);
|
popup.setEnabled(enabled);
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Snowflake",
|
"name": "Snowflake",
|
||||||
"version": "0.0.9",
|
"version": "0.0.9",
|
||||||
"description": "Snowflake is a WebRTC pluggable transport for Tor.",
|
"description": "__MSG_appDesc__",
|
||||||
|
"default_locale": "en_US",
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["snowflake.js"],
|
"scripts": ["snowflake.js"],
|
||||||
"persistent": true
|
"persistent": true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue