feat(i18n): nine languages, each at its own address; release v6.3.0
The site now speaks German, French, Spanish, Ukrainian, Russian, Chinese, Korean and Hindi alongside English — 623 strings per language, 5,607 translations, covering the landing page, the key exchange, the chat, group calls and every error along the way. Each locale is a real page at a real URL (/de/, /fr/, …), generated at build time from locales/*.json. That is the whole point: the app is client-rendered, so a language that only swaps strings at runtime has no address for a crawler to index and no link anyone can share. Each page carries its own canonical, a reciprocal hreflang cluster and translated schema.org. The URL decides the language, always. A stored preference only applies where the address does not say, and nothing ever redirects on Accept-Language — that is how sites become invisible to search engines outside one country. robots.txt and sitemap.xml did not exist before; both are generated now. Bugs found on the way, each with a test that would have caught it: - partner logos used page-relative paths and 404'd from any /xx/ page - post-build stamped ?v= only into the root shell, leaving locales behind - "Back online" appeared on every page load, not just after being offline - update timestamps were hard-coded to US format for every reader - t() threw on a partial window, taking whole components down with it
This commit is contained in:
+4
-3
@@ -1,17 +1,18 @@
|
||||
{
|
||||
"name": "securebit-chat",
|
||||
"version": "6.2.0",
|
||||
"version": "6.3.0",
|
||||
"description": "Secure P2P Communication Application with End-to-End Encryption",
|
||||
"main": "index.html",
|
||||
"scripts": {
|
||||
"build": "npm run build:css && npm run build:js && npm run post-build",
|
||||
"build": "npm run build:css && npm run build:js && npm run build:i18n && npm run post-build",
|
||||
"build:css": "npx tailwindcss -i src/styles/tw-input.css -o assets/tailwind.css --minify --content \"./index.html,./src/**/*.jsx,./src/**/*.js\"",
|
||||
"build:js": "npx esbuild src/app.jsx --bundle --format=esm --outfile=dist/app.js --sourcemap && npx esbuild src/scripts/app-boot.js --bundle --format=esm --outfile=dist/app-boot.js --sourcemap && npx esbuild src/scripts/qr-local.js --bundle --format=esm --outfile=dist/qr-local.js --sourcemap",
|
||||
"build:i18n": "node scripts/build-i18n.js",
|
||||
"post-build": "node scripts/post-build.js",
|
||||
"dev": "npm run build && python -m http.server 8000",
|
||||
"watch": "npx tailwindcss -i src/styles/tw-input.css -o assets/tailwind.css --watch",
|
||||
"serve": "npx http-server -p 8000",
|
||||
"test": "node tests/sas-verification.test.mjs && node tests/verification-gate.test.mjs && node tests/inbound-frame-authentication.test.mjs && node tests/control-frame-authorization.test.mjs && node tests/security-level-shape.test.mjs && node tests/desktop-download-links.test.mjs && node tests/file-transfer-consent.test.mjs && node tests/incoming-message-sanitization.test.mjs && node tests/outgoing-message-integrity.test.mjs && node tests/secure-chat-features.test.mjs && node tests/notification-meta-forwarding.test.mjs && node tests/notification-ephemeral-privacy.test.mjs && node tests/key-derivation-compat.test.mjs && node tests/key-exchange-e2e.test.mjs && node tests/file-type-allowlist.test.mjs && node tests/voice-auto-accept.test.mjs && node tests/legacy-offer-purge.test.mjs && node tests/webrtc-privacy-mode.test.mjs && node tests/indexeddb-metadata-encryption.test.mjs && node tests/disconnect-cleanup.test.mjs && node tests/timer-lifecycle.test.mjs && node tests/file-transfer-cleanup.test.mjs && node tests/file-transfer-ui-cleanup.test.mjs && node tests/file-transfer-callback-propagation.test.mjs && node tests/debug-window-hooks.test.mjs && node tests/inbound-message-rate-limit.test.mjs && node tests/file-transfer-chunk-rate-limit.test.mjs && node tests/ice-servers-validation.test.mjs && node tests/sessions-reducer.test.mjs && node tests/webrtc-sdp.test.mjs && node tests/webrtc-video.test.mjs && node tests/webrtc-adaptation.test.mjs && node tests/session-recovery.test.mjs && node tests/qr-zip-bomb.test.mjs && node tests/ice-gathering-patience.test.mjs && node tests/version-consistency.test.mjs && node tests/double-ratchet.test.mjs && node tests/ratchet-integration.test.mjs && node tests/descriptor-sbq2.test.mjs && node tests/sbq2-key-exchange.test.mjs && node tests/qr-scan-single-frame.test.mjs && node tests/mobile-chat-layout.test.mjs && node tests/group-crypto.test.mjs && node tests/groups-reducer.test.mjs && node tests/group-session-e2e.test.mjs && node tests/group-app-integration.test.mjs && node tests/group-sender.test.mjs && node tests/group-mesh.test.mjs && node tests/apple-motion.test.mjs"
|
||||
"test": "node tests/sas-verification.test.mjs && node tests/verification-gate.test.mjs && node tests/inbound-frame-authentication.test.mjs && node tests/control-frame-authorization.test.mjs && node tests/security-level-shape.test.mjs && node tests/desktop-download-links.test.mjs && node tests/file-transfer-consent.test.mjs && node tests/incoming-message-sanitization.test.mjs && node tests/outgoing-message-integrity.test.mjs && node tests/secure-chat-features.test.mjs && node tests/notification-meta-forwarding.test.mjs && node tests/notification-ephemeral-privacy.test.mjs && node tests/key-derivation-compat.test.mjs && node tests/key-exchange-e2e.test.mjs && node tests/file-type-allowlist.test.mjs && node tests/voice-auto-accept.test.mjs && node tests/legacy-offer-purge.test.mjs && node tests/webrtc-privacy-mode.test.mjs && node tests/indexeddb-metadata-encryption.test.mjs && node tests/disconnect-cleanup.test.mjs && node tests/timer-lifecycle.test.mjs && node tests/file-transfer-cleanup.test.mjs && node tests/file-transfer-ui-cleanup.test.mjs && node tests/file-transfer-callback-propagation.test.mjs && node tests/debug-window-hooks.test.mjs && node tests/inbound-message-rate-limit.test.mjs && node tests/file-transfer-chunk-rate-limit.test.mjs && node tests/ice-servers-validation.test.mjs && node tests/sessions-reducer.test.mjs && node tests/webrtc-sdp.test.mjs && node tests/webrtc-video.test.mjs && node tests/webrtc-adaptation.test.mjs && node tests/session-recovery.test.mjs && node tests/qr-zip-bomb.test.mjs && node tests/ice-gathering-patience.test.mjs && node tests/version-consistency.test.mjs && node tests/i18n-build.test.mjs && node tests/i18n-runtime.test.mjs && node tests/language-switcher.test.mjs && node tests/asset-paths-locale-safe.test.mjs && node tests/double-ratchet.test.mjs && node tests/ratchet-integration.test.mjs && node tests/descriptor-sbq2.test.mjs && node tests/sbq2-key-exchange.test.mjs && node tests/qr-scan-single-frame.test.mjs && node tests/mobile-chat-layout.test.mjs && node tests/group-crypto.test.mjs && node tests/groups-reducer.test.mjs && node tests/group-session-e2e.test.mjs && node tests/group-app-integration.test.mjs && node tests/group-sender.test.mjs && node tests/group-mesh.test.mjs && node tests/apple-motion.test.mjs"
|
||||
},
|
||||
"keywords": [
|
||||
"p2p",
|
||||
|
||||
Reference in New Issue
Block a user