Skip to content

Commit ee46110

Browse files
authored
Merge branch 'main' into rimehrab-patch-1
2 parents 5b376fc + 1639a1b commit ee46110

53 files changed

Lines changed: 2287 additions & 451 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

public/banner.js

Lines changed: 78 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
* lang=fr Override the browser language (default: auto-detected)
1414
* id=myDiv Insert the banner inside the element with this id
1515
* (default: prepend to <body>)
16-
* size=normal Banner size: "normal" (default) or "mini"
16+
* size=normal Banner size: "normal" (default), "mini" or "minimal"
1717
* link=URL Make the banner text a link (default: https://keepandroidopen.org)
1818
* Set link=none to disable the link
1919
* hidebutton=on Show an X close button (default: on)
2020
* Set hidebutton=off to hide the close button
21+
* animation=on Add animation to border of banner (default: on)
22+
* Set animation=off to disable
2123
*/
2224
(function () {
2325
"use strict";
@@ -26,10 +28,13 @@
2628
var messages = {
2729
fa: "اندروید، یک سکّوی بسته خواهد شد!",
2830
ar: "سيصبح نظام أندرويد منصة مغلقة في",
29-
en: "Android will become a locked-down platform",
31+
he: "אנדרואיד תהפוך לפלטפורמה נעולה בעוד",
32+
en: "Android will become a locked-down platform in",
3033
ca: "Android es convertir\u00E0 en una plataforma tancada",
31-
cs: "Android will become a locked-down platform in",
34+
cs: "Android se stane uzamčenou platformou za",
3235
de: "Android wird eine geschlossene Plattform werden.",
36+
da: "Android vil blive en lukket platform om",
37+
nl: "Android zal een gesloten platform worden over",
3338
el: "\u03A4\u03BF Android \u03B8\u03B1 \u03B3\u03AF\u03BD\u03B5\u03B9 \u03BC\u03AF\u03B1 \u03BA\u03BB\u03B5\u03B9\u03C3\u03C4\u03AE \u03C0\u03BB\u03B1\u03C4\u03C6\u03CC\u03C1\u03BC\u03B1",
3439
es: "Android se convertir\u00E1 en una plataforma cerrada",
3540
fr: "Android va devenir une plateforme ferm\u00E9e",
@@ -44,8 +49,11 @@
4449
tr: "Android k\u0131s\u0131tl\u0131 bir platform haline gelecek.",
4550
uk: "Android \u0441\u0442\u0430\u043D\u0435 \u0437\u0430\u043A\u0440\u0438\u0442\u043E\u044E \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u044E",
4651
"zh-CN": "\u5B89\u5353\u5C06\u6210\u4E3A\u4E00\u4E2A\u5C01\u95ED\u5E73\u53F0",
47-
"zh-TW": "\u5012\u6578 Android \u5373\u5C07\u6DEA\u70BA\u756B\u5730\u70BA\u7262\u3001\u684E\u688F\u6EFF\u76C8\u7684\u5C01\u9589\u5E73\u81FA",
48-
ja: "Androidは閉鎖的なプラットフォームになろうとしています"
52+
"zh-TW": "Android \u5C07\u6210\u70BA\u4E00\u500B\u5C01\u9589\u5E73\u53F0",
53+
ja: "Androidは閉鎖的なプラットフォームになろうとしています",
54+
fi: "Androidista tulee suljettu alusta",
55+
hu: "Az Android egy lezárt platform lesz",
56+
vi: "Android sẽ trở thành một hệ điều hành đóng",
4957
};
5058

5159
// ── Parse query parameters from the script's own src URL ──────────────
@@ -70,15 +78,21 @@
7078
// ── Determine locale ──────────────────────────────────────────────────
7179
function resolveLocale(tag) {
7280
if (!tag) return "en";
81+
// Exact match
7382
if (messages[tag]) return tag;
83+
// Case-insensitive exact match (e.g. "pt-br" → "pt-BR")
7484
var lower = tag.toLowerCase();
7585
for (var key in messages) {
7686
if (key.toLowerCase() === lower) return key;
7787
}
78-
var base = tag.split("-")[0].toLowerCase();
79-
if (messages[base]) return base;
88+
// Fallback to base language (e.g. "de-CH" → "de", "zh-Hans" → "zh")
89+
var base = lower.split("-")[0];
8090
for (var key2 in messages) {
81-
if (key2.toLowerCase().split("-")[0] === base) return key2;
91+
if (key2.toLowerCase() === base) return key2;
92+
}
93+
// Fallback to any regional variant of the base language (e.g. "pt" → "pt-BR")
94+
for (var key3 in messages) {
95+
if (key3.toLowerCase().split("-")[0] === base) return key3;
8296
}
8397
return "en";
8498
}
@@ -91,11 +105,15 @@
91105
);
92106

93107
// ── Size variant ──────────────────────────────────────────────────────
94-
var size = params.size === "mini" ? "mini" : "normal";
108+
var size = params.size === "mini" ? "mini"
109+
: params.size === "minimal"
110+
? "minimal"
111+
: "normal";
95112

96113
// ── Link ────────────────────────────────────────────────────────────
97114
var linkParam = params.link;
98-
var linkUrl = linkParam === "none" ? null : (linkParam || "https://keepandroidopen.org");
115+
var defaultLink = "https://keepandroidopen.org" + (locale === "en" ? "" : "/" + locale + "/");
116+
var linkUrl = linkParam === "none" ? null : (linkParam || defaultLink);
99117

100118
// ── Close button ────────────────────────────────────────────────────
101119
var showClose = params.hidebutton !== "off";
@@ -122,7 +140,6 @@
122140
"0px 3px 0px #751111," +
123141
"0px 4px 0px #5e0d0d," +
124142
"0px 6px 10px rgba(0,0,0,0.5);" +
125-
"animation:kao-pulse 2s infinite;" +
126143
"padding:0.5rem 2.5rem;" +
127144
"line-height:1.6;" +
128145
"box-sizing:border-box;" +
@@ -145,12 +162,33 @@
145162
"0px 1px 0px #9e1a1a," +
146163
"0px 2px 0px #8a1515," +
147164
"0px 3px 5px rgba(0,0,0,0.4);" +
148-
"animation:kao-pulse 2s infinite;" +
149165
"padding:0.25rem 1.5rem;" +
150166
"line-height:1.4;" +
151167
"box-sizing:border-box;" +
152168
"}";
153169

170+
var cssMinimal =
171+
".kao-banner{" +
172+
"position:relative;" +
173+
"font-variant-numeric:tabular-nums;" +
174+
"background:linear-gradient(180deg,#d32f2f 0%,#b71c1c 100%);" +
175+
"border-bottom:2px solid #801313;" +
176+
"color:#fff;" +
177+
"font-family:'Arial Black',sans-serif;" +
178+
"font-weight:900;" +
179+
"text-transform:uppercase;" +
180+
"letter-spacing:1px;" +
181+
"font-size:0.75rem;" +
182+
"text-align:center;" +
183+
"text-shadow:" +
184+
"0px 1px 0px #9e1a1a," +
185+
"0px 2px 0px #8a1515," +
186+
"0px 3px 5px rgba(0,0,0,0.4);" +
187+
"padding:0.25rem 1.5rem;" +
188+
"line-height:1.4;" +
189+
"box-sizing:border-box;" +
190+
"}";
191+
154192
var cssCommon =
155193
".kao-banner a{color:#fff;text-decoration:none;}" +
156194
".kao-banner a:hover{text-decoration:underline;}" +
@@ -169,15 +207,20 @@
169207
"line-height:1;" +
170208
"text-shadow:none;" +
171209
"}" +
172-
".kao-banner-close:hover{opacity:1;}" +
210+
".kao-banner-close:hover{opacity:1;}";
211+
212+
var cssKaoPulse =
213+
".kao-banner:not(.no-animation) { animation:kao-pulse 2s infinite; }" +
173214
"@keyframes kao-pulse{" +
174215
"0%{box-shadow:0 0 0 0 rgba(211,47,47,0.7)}" +
175216
"70%{box-shadow:0 0 0 15px rgba(211,47,47,0)}" +
176217
"100%{box-shadow:0 0 0 0 rgba(211,47,47,0)}" +
177218
"}";
178219

179220
var style = document.createElement("style");
180-
style.textContent = (size === "mini" ? cssMini : cssNormal) + cssCommon;
221+
style.textContent = (size === "mini" ? cssMini : size === "minimal" ? cssMinimal : cssNormal)
222+
+ (params.animation === "off" ? "" : cssKaoPulse)
223+
+ cssCommon;
181224
document.head.appendChild(style);
182225

183226
// ── Check if previously dismissed (reappears after dismissDays) ─────
@@ -194,7 +237,7 @@
194237

195238
// ── Create banner DOM ─────────────────────────────────────────────────
196239
var banner = document.createElement("div");
197-
banner.className = "kao-banner";
240+
banner.className = params.animation === "off" ? "kao-banner no-animation" : "kao-banner";
198241

199242
var messageText = messages[locale] || messages.en;
200243

@@ -209,7 +252,11 @@
209252
banner.appendChild(document.createTextNode(messageText));
210253
}
211254

212-
banner.appendChild(document.createElement("br"));
255+
if (params.size === "minimal") {
256+
banner.appendChild(document.createTextNode("\u00A0"));
257+
} else {
258+
banner.appendChild(document.createElement("br"));
259+
}
213260

214261
var countdownSpan = document.createElement("span");
215262
countdownSpan.textContent = "\u00A0";
@@ -244,73 +291,15 @@
244291
// ── Countdown logic ───────────────────────────────────────────────────
245292
var countDownDate = new Date("Sep 1, 2026 00:00:00").getTime();
246293

247-
var formatter = new Intl.RelativeTimeFormat(locale, { style: "narrow" });
248-
249-
var pfx = new Array(4);
250-
var sfx = new Array(4);
251-
252-
function getOffset(unit) {
253-
switch (unit) {
254-
case "day": return 0;
255-
case "hour": return 1;
256-
case "minute": return 2;
257-
case "second": return 3;
258-
}
259-
}
260-
261-
function extractCommon(p, c, reverse) {
262-
var s = 0;
263-
var w = 0;
264-
var i = reverse ? p.length - 1 : 0;
265-
var j = reverse ? c.length - 1 : 0;
266-
var pEnd = reverse ? 0 : p.length;
267-
var cEnd = reverse ? 0 : c.length;
268-
var chr;
269-
while (
270-
(reverse ? i >= pEnd : i < pEnd) &&
271-
(reverse ? j >= cEnd : j < cEnd) &&
272-
(chr = p[reverse ? i-- : i++]) === c[reverse ? j-- : j++]
273-
) {
274-
w = chr === " " ? w + 1 : 0;
275-
s++;
276-
}
277-
return s - w;
278-
}
279-
280-
function cacheFormattingInfo(value, unit) {
281-
var p = formatter.formatToParts(value, unit);
282-
if (!p.length) return;
283-
var c = formatter.formatToParts(-value, unit);
284-
285-
var offset = getOffset(unit);
286-
if (p[0].type === "literal" && (!c.length || c[0].type !== "literal" || !c[0].value.endsWith(p[0].value))) {
287-
pfx[offset] = p[0].value.length;
288-
}
289-
if (p[p.length - 1].type === "literal") {
290-
if (!c.length || c[c.length - 1].type !== "literal") {
291-
sfx[offset] = p[p.length - 1].value.length;
292-
} else if (!c[c.length - 1].value.startsWith(p[p.length - 1].value)) {
293-
sfx[offset] =
294-
p[p.length - 1].value.length -
295-
extractCommon(p[p.length - 1].value, c[c.length - 1].value, false);
296-
}
297-
}
298-
}
294+
var unitFormatters = {
295+
day: new Intl.NumberFormat(locale, { style: "unit", unit: "day", unitDisplay: "narrow" }),
296+
hour: new Intl.NumberFormat(locale, { style: "unit", unit: "hour", unitDisplay: "narrow" }),
297+
minute: new Intl.NumberFormat(locale, { style: "unit", unit: "minute", unitDisplay: "narrow" }),
298+
second: new Intl.NumberFormat(locale, { style: "unit", unit: "second", unitDisplay: "narrow" })
299+
};
299300

300-
cacheFormattingInfo(1, "day");
301-
cacheFormattingInfo(2, "hour");
302-
cacheFormattingInfo(3, "minute");
303-
cacheFormattingInfo(4, "second");
304-
305-
function getLocalizedUnit(value, unit, trimConjunction, trimSuffix) {
306-
var offset = getOffset(unit);
307-
var string = formatter.format(value, unit);
308-
var p = pfx[offset];
309-
var s = sfx[offset];
310-
return string.slice(
311-
trimConjunction && p || (p == 1 && string[0] === "+") ? pfx[offset] : 0,
312-
trimSuffix && s ? -sfx[offset] : string.length
313-
);
301+
function formatUnit(value, unit) {
302+
return unitFormatters[unit].format(value);
314303
}
315304

316305
var remaining = new Array(7);
@@ -329,19 +318,22 @@
329318
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
330319

331320
var parts = 0;
332-
remaining[0] = days > 0 ? getLocalizedUnit(days, "day", parts++, true) : null;
321+
remaining[0] = days > 0 ? formatUnit(days, "day") : null;
322+
if (remaining[0]) parts++;
333323
remaining[1] = parts ? separator : null;
334324
remaining[2] =
335325
parts || hours > 0
336-
? getLocalizedUnit(hours, "hour", parts++, true)
326+
? formatUnit(hours, "hour")
337327
: null;
328+
if (remaining[2]) parts++;
338329
remaining[3] = parts ? separator : null;
339330
remaining[4] =
340331
parts || minutes > 0
341-
? getLocalizedUnit(minutes, "minute", parts++, true)
332+
? formatUnit(minutes, "minute")
342333
: null;
334+
if (remaining[4]) parts++;
343335
remaining[5] = parts ? separator : null;
344-
remaining[6] = getLocalizedUnit(seconds, "second", parts++, false);
336+
remaining[6] = formatUnit(seconds, "second");
345337

346338
countdownSpan.textContent = remaining.join("");
347339

public/img/bluesky.svg

Lines changed: 1 addition & 0 deletions
Loading

public/img/linkedin.svg

Lines changed: 1 addition & 0 deletions
Loading

public/img/logos/brave.com.png

1.08 KB
Loading

public/img/logos/cryptpad.org.png

14.5 KB
Loading

public/img/logos/fedimedia.it.png

32.9 KB
Loading
550 Bytes
Loading

public/img/logos/fosdem.org.png

3.58 KB
Loading

public/img/logos/fulu.org.png

26.5 KB
Loading
913 Bytes
Loading

0 commit comments

Comments
 (0)