mirror of
https://gitlab.com/timvisee/send.git
synced 2025-12-08 19:33:24 +00:00
Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea1ea2aa68 | ||
|
|
90d06d71d3 | ||
|
|
11f2deb7a6 | ||
|
|
0f5edf023a | ||
|
|
3be0621647 | ||
|
|
fc07bfdb85 | ||
|
|
581a989304 | ||
|
|
047d6a85ab | ||
|
|
90f6a07d4a | ||
|
|
8f4a53db64 | ||
|
|
c2dd51c638 | ||
|
|
cdd98af86a | ||
|
|
883f2bc0f9 | ||
|
|
94f1eabbc7 | ||
|
|
902bc6628e | ||
|
|
460b741f17 | ||
|
|
d5c488196d | ||
|
|
9ad9c9feb2 | ||
|
|
6576e4a74c | ||
|
|
950872109e | ||
|
|
87051d27ed | ||
|
|
3451803b37 | ||
|
|
ac15153e8f | ||
|
|
924f5dc682 | ||
|
|
ff9be6a213 | ||
|
|
883728570e | ||
|
|
0435f17f9a | ||
|
|
1e1268fff0 | ||
|
|
252d7817e3 | ||
|
|
ce28c38ebe | ||
|
|
f0407f9beb | ||
|
|
c6f222eb57 | ||
|
|
6dd6135185 | ||
|
|
8df339b66d | ||
|
|
8702fda651 | ||
|
|
807ecff471 | ||
|
|
927c981cd7 | ||
|
|
7073cc8ce6 | ||
|
|
c925fae696 | ||
|
|
966d7a5e35 | ||
|
|
96c750c098 | ||
|
|
0729064753 | ||
|
|
259a5a5f24 | ||
|
|
27be72e0cd | ||
|
|
e4231bbc0f | ||
|
|
1d184f06bf | ||
|
|
f7b46a99ac | ||
|
|
3fadb489c7 | ||
|
|
6378676c2d | ||
|
|
014d84e4c7 | ||
|
|
a08d8435a9 | ||
|
|
40a05c9ecf | ||
|
|
527040afef | ||
|
|
a48a447808 | ||
|
|
f3569d7f98 | ||
|
|
6ca7d11efb | ||
|
|
b71ae4a0ff | ||
|
|
7ba25664b5 | ||
|
|
80fb42ad3d | ||
|
|
f036df5f47 | ||
|
|
20c063db7c | ||
|
|
a6b43c9eef | ||
|
|
c80f9ada65 | ||
|
|
e0ae5cb3c6 | ||
|
|
c0fb3d17be | ||
|
|
116f090b7e | ||
|
|
7cbd9716e2 | ||
|
|
58191975b9 | ||
|
|
76695aee5d | ||
|
|
b356b4cad3 | ||
|
|
63ddbeefc4 | ||
|
|
7b423b24b6 | ||
|
|
b67050b742 | ||
|
|
06242dfd38 | ||
|
|
3b8dbfd81c | ||
|
|
9c2fe39764 | ||
|
|
8b21d43bfa | ||
|
|
e7e39f4d4a | ||
|
|
e4c801d9a1 | ||
|
|
324f275dd4 | ||
|
|
594e0bd28e | ||
|
|
6a7fdfe780 | ||
|
|
0c82741b98 | ||
|
|
fe57734792 | ||
|
|
4754bed9b8 | ||
|
|
a60da467b9 | ||
|
|
362da2bbfc | ||
|
|
1a9ef4a246 | ||
|
|
f51dbbb8f5 | ||
|
|
e497107e59 | ||
|
|
10ad6fc1ae | ||
|
|
c982db4c75 | ||
|
|
cd8130563d | ||
|
|
730a569d43 | ||
|
|
769dae1bdc | ||
|
|
54a8c504ce | ||
|
|
92dc9a0f71 | ||
|
|
80a7c92056 | ||
|
|
c6ebea0100 | ||
|
|
039b5daaed | ||
|
|
4bf4e61c2c | ||
|
|
3c21e2a00f | ||
|
|
38a379d1de | ||
|
|
adeb19d974 | ||
|
|
744c410704 | ||
|
|
99ab3882eb | ||
|
|
7cdf566bcd | ||
|
|
b6e4877d93 | ||
|
|
b9c87fd779 | ||
|
|
6ef5b5133c | ||
|
|
b7d2420765 | ||
|
|
c139531c91 | ||
|
|
88fe3902bc | ||
|
|
645fd062ac | ||
|
|
ccb0b71df5 | ||
|
|
b8ec90a398 | ||
|
|
7ed5f37c66 | ||
|
|
c899129f9a | ||
|
|
1bb91690c5 | ||
|
|
073f6f67d3 | ||
|
|
533bfdb496 | ||
|
|
34de65d7d2 | ||
|
|
209fdf34f8 | ||
|
|
ba5c2a049d | ||
|
|
1528aa3f1b |
@@ -1,10 +1,8 @@
|
||||
node_modules
|
||||
.git
|
||||
.tox
|
||||
.DS_Store
|
||||
firefox
|
||||
assets
|
||||
docs
|
||||
test
|
||||
coverage
|
||||
.circleci
|
||||
.nyc_output
|
||||
.vscode
|
||||
.DS_Store
|
||||
coverage
|
||||
docs
|
||||
firefox
|
||||
node_modules
|
||||
@@ -2,5 +2,6 @@ dist
|
||||
assets
|
||||
firefox
|
||||
coverage
|
||||
android/app/build
|
||||
app/locale.js
|
||||
app/capabilities.js
|
||||
@@ -4,6 +4,7 @@ env:
|
||||
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- prettier
|
||||
- plugin:node/recommended
|
||||
- plugin:security/recommended
|
||||
|
||||
@@ -22,13 +23,5 @@ rules:
|
||||
security/detect-non-literal-fs-filename: off
|
||||
security/detect-object-injection: off
|
||||
|
||||
eol-last: [error, always]
|
||||
eqeqeq: error
|
||||
no-alert: warn
|
||||
no-console: warn
|
||||
no-path-concat: error
|
||||
no-unused-vars: [error, {argsIgnorePattern: "^_|err|event|next|reject"}]
|
||||
no-var: error
|
||||
one-var: [error, never]
|
||||
prefer-const: error
|
||||
quotes: [error, single, {avoidEscape: true}]
|
||||
require-atomic-updates: warn
|
||||
|
||||
41
CONTRIBUTORS
41
CONTRIBUTORS
@@ -4,15 +4,18 @@ Adnan Kičin
|
||||
Alberto Castro
|
||||
Alexander Slovesnik
|
||||
Alfredos-Panagiotis Damkalis
|
||||
Aman Alam
|
||||
Amin Mahmudian
|
||||
Ander Elortondo
|
||||
Andreas Pettersson
|
||||
Anesu Chiodza
|
||||
Anika Dorn
|
||||
Anish Sheela
|
||||
Arash Mousavi
|
||||
Artem Polivanchuk
|
||||
Ashikur Rahman
|
||||
Ashok kumar
|
||||
Balasankar C
|
||||
Balázs Meskó
|
||||
Belayet Hossain
|
||||
Benjamin Forehand Jr
|
||||
@@ -20,8 +23,11 @@ Besnik Bleta
|
||||
Björn I
|
||||
Bjørn I
|
||||
Boopesh Mahendran
|
||||
Brahim Essaidi
|
||||
Brainlulz
|
||||
Breana Gonzales
|
||||
Christian Elbrianno
|
||||
Christoph Kührer
|
||||
Christopher Ramírez
|
||||
Chuck Harmston
|
||||
Cloney 173741
|
||||
@@ -31,6 +37,7 @@ Cynthia Pereira
|
||||
Daniel Thorn
|
||||
Daniela Arcese
|
||||
Danny Coates
|
||||
Davide
|
||||
Derek Tamsen
|
||||
Dhyey Thakore
|
||||
Donovan Preston
|
||||
@@ -52,11 +59,16 @@ Frederick Villaluna
|
||||
G12r
|
||||
Gabriela
|
||||
Gautam krishna.R
|
||||
George Raptis
|
||||
Georgianizator
|
||||
Gonçalo Matos
|
||||
Gwenn
|
||||
Hugo
|
||||
Hugo Abreu
|
||||
Hyeonseok Shin
|
||||
Håvar Henriksen
|
||||
Ian Neal
|
||||
ItielMaN
|
||||
Jae Hyeon Park
|
||||
Jakob Kappel
|
||||
Jakub Rychlý
|
||||
@@ -65,6 +77,8 @@ Jarmo
|
||||
Jim Spentzos
|
||||
Jiri Grönroos
|
||||
Jobava
|
||||
Joe Becher
|
||||
Joe ST
|
||||
Joergen
|
||||
Johann-S
|
||||
John Gruen
|
||||
@@ -81,9 +95,11 @@ Khaled Hosny
|
||||
Kim Ludvigsen
|
||||
Kohei Yoshino
|
||||
Lan Glad
|
||||
Lasse Liehu
|
||||
Laurent Jouanneau
|
||||
Lobodzets
|
||||
LuFlo
|
||||
Luis A. Sánchez
|
||||
Luiz Carlos de Morais
|
||||
Luna Jernberg
|
||||
Mahay Alam Khan
|
||||
@@ -106,14 +122,18 @@ Michal Vašíček
|
||||
Mikeyy
|
||||
Miro Rauhala
|
||||
Mozilla Pontoon
|
||||
Mozilla-GitHub-Standards
|
||||
Mozinet
|
||||
Moḥend Belqasem
|
||||
Muhend Belkacem
|
||||
Muḥend Belqasem
|
||||
Myungjae Won
|
||||
Nicholas Skinsacos
|
||||
Nihad
|
||||
Nihad Suljić
|
||||
Oscar
|
||||
Paulius
|
||||
Pedro Burlamaqui Bendahan
|
||||
Peter deHaan
|
||||
Pierre Neter
|
||||
Pin-guang Chen
|
||||
@@ -125,10 +145,12 @@ RickieES
|
||||
Rimas Kudelis
|
||||
Rizky Ariestiyansyah
|
||||
Rob Powell
|
||||
Robert
|
||||
Roberto Alvarado
|
||||
Rodrigo
|
||||
Rodrigo Guerra
|
||||
Rok Žerdin
|
||||
Romi Hardiyanto
|
||||
Rongjian Zhang
|
||||
Ruba
|
||||
Sahithi
|
||||
@@ -139,9 +161,12 @@ Sara Todaro
|
||||
Sav22999
|
||||
Schieck :)
|
||||
Selim Şumlu
|
||||
Sidak Singh Aulakh
|
||||
Slimane Amiri
|
||||
Slimane Selyan AMIRI
|
||||
Soumya Himanish Mohapatra
|
||||
Staś Małolepszy
|
||||
Suriyaa ✌️️
|
||||
Tema
|
||||
Thomas Dalichow
|
||||
Théo Chevalier
|
||||
@@ -150,6 +175,7 @@ Tim Visée
|
||||
Tomer Cohen
|
||||
Tomáš Zelina
|
||||
Ton
|
||||
Top
|
||||
Tymur Faradzhev
|
||||
Uccen Marzuq
|
||||
Varghese Thomas
|
||||
@@ -159,6 +185,7 @@ Vitaliy Krutko
|
||||
Weihang Lo
|
||||
Wil Clouser
|
||||
YFdyh000
|
||||
Yassine Aït-El-Mouden
|
||||
Yongmin H
|
||||
You-Wen Liang (Mark)
|
||||
aaaaalbert
|
||||
@@ -169,6 +196,7 @@ alex_mayorga
|
||||
ariestiyansyah
|
||||
avelper
|
||||
chilledfrogs
|
||||
clouserw-mozilla-owner
|
||||
dgadelha
|
||||
dskmori
|
||||
ehuggett
|
||||
@@ -180,25 +208,35 @@ gmontagu
|
||||
goofy
|
||||
hello
|
||||
hi
|
||||
ivan.pompa
|
||||
jesferman1993
|
||||
jlG
|
||||
josotrix
|
||||
jspam
|
||||
julenx
|
||||
kenrick95
|
||||
kumincir
|
||||
m4hdi.pdroid
|
||||
mail
|
||||
manxmensch
|
||||
marigalicer
|
||||
marsf
|
||||
merianosnikos
|
||||
mirzet.omerovic.1992
|
||||
mujeebcpy
|
||||
p.sanroman.bengoetxea
|
||||
passionforlife
|
||||
paul.trevor
|
||||
pyup.io bot
|
||||
ravmn
|
||||
rcmainak
|
||||
reza.habibi2008
|
||||
rgpublic
|
||||
risger
|
||||
robbp
|
||||
ruikunai
|
||||
savemore99.sm
|
||||
sergio
|
||||
shikhar-scs
|
||||
siparon
|
||||
skystar-p
|
||||
@@ -210,10 +248,13 @@ victor.gonzalezro
|
||||
xcffl
|
||||
ybouhamam
|
||||
yoshimitsu002
|
||||
yusup.ramdani
|
||||
Μιχάλης
|
||||
Марко Костић (Marko Kostić)
|
||||
Ратко Вујановић
|
||||
صفا الفليج
|
||||
వీవెన్
|
||||
ജോയ്സ്
|
||||
张无忌
|
||||
新垣结衣松冈茉优长泽雅美门胁麦上野树里石原里美
|
||||
莫非前世那一眼
|
||||
|
||||
61
Dockerfile
61
Dockerfile
@@ -1,18 +1,59 @@
|
||||
FROM node:10 AS builder
|
||||
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app
|
||||
COPY package*.json /app/
|
||||
WORKDIR /app
|
||||
RUN npm install --production
|
||||
##
|
||||
# Firefox Send - Mozilla
|
||||
#
|
||||
# License https://github.com/mozilla/send/blob/master/LICENSE
|
||||
##
|
||||
|
||||
FROM node:10-slim
|
||||
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app
|
||||
|
||||
# Build project
|
||||
FROM node:10 AS builder
|
||||
RUN set -x \
|
||||
# Add user
|
||||
&& addgroup --gid 10001 app \
|
||||
&& adduser --disabled-password \
|
||||
--gecos '' \
|
||||
--gid 10001 \
|
||||
--home /app \
|
||||
--uid 10001 \
|
||||
app
|
||||
COPY --chown=app:app . /app
|
||||
USER app
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app --from=builder /app .
|
||||
COPY --chown=app:app . .
|
||||
RUN ls -la
|
||||
RUN set -x \
|
||||
# Build
|
||||
&& npm ci \
|
||||
&& npm run build
|
||||
|
||||
|
||||
# Main image
|
||||
FROM node:10-slim
|
||||
RUN set -x \
|
||||
# Add user
|
||||
&& addgroup --gid 10001 app \
|
||||
&& adduser --disabled-password \
|
||||
--gecos '' \
|
||||
--gid 10001 \
|
||||
--home /app \
|
||||
--uid 10001 \
|
||||
app
|
||||
RUN apt-get update && apt-get -y install git-core
|
||||
USER app
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app package*.json ./
|
||||
COPY --chown=app:app app app
|
||||
COPY --chown=app:app common common
|
||||
COPY --chown=app:app public/locales public/locales
|
||||
COPY --chown=app:app server server
|
||||
COPY --chown=app:app --from=builder /app/dist dist
|
||||
|
||||
RUN ls -la
|
||||
RUN npm ci --production && npm cache clean --force
|
||||
RUN mkdir -p /app/.config/configstore
|
||||
RUN ln -s dist/version.json version.json
|
||||
|
||||
ENV PORT=1443
|
||||
EXPOSE $PORT
|
||||
|
||||
EXPOSE ${PORT}
|
||||
|
||||
CMD ["node", "server/bin/prod.js"]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* [Localization](#localization)
|
||||
* [Contributing](#contributing)
|
||||
* [Testing](#testing)
|
||||
* [Deployment](#deployment)
|
||||
* [Android](#android)
|
||||
* [License](#license)
|
||||
|
||||
@@ -29,7 +30,7 @@ A file sharing experiment which allows you to send encrypted files to other user
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Node.js 10.0+](https://nodejs.org/)
|
||||
- [Node.js 10.x](https://nodejs.org/)
|
||||
- [Redis server](https://redis.io/) (optional for development)
|
||||
- [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional)
|
||||
|
||||
@@ -91,6 +92,12 @@ Pull requests are always welcome! Feel free to check out the list of ["good firs
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
see also [docs/deployment.md](docs/deployment.md)
|
||||
|
||||
---
|
||||
|
||||
## Android
|
||||
|
||||
The android implementation is contained in the `android` directory, and can be viewed locally for easy testing and editing by running `ANDROID=1 npm start` and then visiting <http://localhost:8080>. CSS and image files are located in the `android/app/src/main/assets` directory.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/* global window, navigator */
|
||||
import 'fluent-intl-polyfill';
|
||||
import 'intl-pluralrules';
|
||||
import choo from 'choo';
|
||||
import html from 'choo/html';
|
||||
import Raven from 'raven-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
import { setApiUrlPrefix, getConstants } from '../app/api';
|
||||
import metrics from '../app/metrics';
|
||||
@@ -53,7 +52,7 @@ function body(main) {
|
||||
|
||||
const menu = html`<a
|
||||
id="hamburger"
|
||||
class="absolute pin-t pin-r z-50"
|
||||
class="absolute top-0 right-0 z-50"
|
||||
href="#"
|
||||
onclick="${clickPreferences}"
|
||||
>
|
||||
@@ -83,7 +82,7 @@ function body(main) {
|
||||
state.archive = new Archive([], DEFAULTS.EXPIRE_SECONDS);
|
||||
state.storage = storage;
|
||||
state.user = new User(storage, LIMITS);
|
||||
state.raven = Raven;
|
||||
state.sentry = Sentry;
|
||||
});
|
||||
app.use(metrics);
|
||||
app.route('/', body(home));
|
||||
|
||||
@@ -42,11 +42,7 @@ module.exports = function(state, emit) {
|
||||
content =
|
||||
archives.length < 1
|
||||
? intro(state)
|
||||
: list(
|
||||
archives,
|
||||
'list-reset h-full overflow-y-auto w-full',
|
||||
'mb-3 w-full'
|
||||
);
|
||||
: list(archives, 'h-full overflow-y-auto w-full', 'mb-3 w-full');
|
||||
}
|
||||
|
||||
return html`
|
||||
@@ -57,7 +53,7 @@ module.exports = function(state, emit) {
|
||||
>
|
||||
${content}
|
||||
</section>
|
||||
<div class="fixed pin-r pin-b z-20">
|
||||
<div class="fixed right-0 bottom-0 z-20">
|
||||
${button}
|
||||
<input
|
||||
id="file-upload"
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function initialState(state, emitter) {
|
||||
getAsset(name) {
|
||||
return `${state.prefix}/${name}`;
|
||||
},
|
||||
raven: {
|
||||
sentry: {
|
||||
captureException: e => {
|
||||
console.error('ERROR ' + e + ' ' + e.stack);
|
||||
}
|
||||
|
||||
78
app/api.js
78
app/api.js
@@ -11,6 +11,15 @@ if (!fileProtocolWssUrl) {
|
||||
fileProtocolWssUrl = 'wss://send.firefox.com/api/ws';
|
||||
}
|
||||
|
||||
export class ConnectionError extends Error {
|
||||
constructor(cancelled, duration, size) {
|
||||
super(cancelled ? '0' : 'connection closed');
|
||||
this.cancelled = cancelled;
|
||||
this.duration = duration;
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
export function setFileProtocolWssUrl(url) {
|
||||
localStorage && localStorage.setItem('wssURL', url);
|
||||
fileProtocolWssUrl = url;
|
||||
@@ -137,17 +146,25 @@ export async function setPassword(id, owner_token, keychain) {
|
||||
}
|
||||
|
||||
function asyncInitWebSocket(server) {
|
||||
return new Promise(resolve => {
|
||||
const ws = new WebSocket(server);
|
||||
ws.onopen = () => {
|
||||
resolve(ws);
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const ws = new WebSocket(server);
|
||||
ws.addEventListener('open', () => resolve(ws), { once: true });
|
||||
} catch (e) {
|
||||
reject(new ConnectionError(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function listenForResponse(ws, canceller) {
|
||||
return new Promise((resolve, reject) => {
|
||||
function handleClose(event) {
|
||||
// a 'close' event before a 'message' event means the request failed
|
||||
ws.removeEventListener('message', handleMessage);
|
||||
reject(new ConnectionError(canceller.cancelled));
|
||||
}
|
||||
function handleMessage(msg) {
|
||||
ws.removeEventListener('close', handleClose);
|
||||
try {
|
||||
const response = JSON.parse(msg.data);
|
||||
if (response.error) {
|
||||
@@ -156,13 +173,11 @@ function listenForResponse(ws, canceller) {
|
||||
resolve(response);
|
||||
}
|
||||
} catch (e) {
|
||||
ws.close();
|
||||
canceller.cancelled = true;
|
||||
canceller.error = e;
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
ws.addEventListener('message', handleMessage, { once: true });
|
||||
ws.addEventListener('close', handleClose, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -176,6 +191,8 @@ async function upload(
|
||||
onprogress,
|
||||
canceller
|
||||
) {
|
||||
let size = 0;
|
||||
const start = Date.now();
|
||||
const host = window.location.hostname;
|
||||
const port = window.location.port;
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
@@ -203,31 +220,41 @@ async function upload(
|
||||
|
||||
const reader = stream.getReader();
|
||||
let state = await reader.read();
|
||||
let size = 0;
|
||||
while (!state.done) {
|
||||
const buf = state.value;
|
||||
if (canceller.cancelled) {
|
||||
throw canceller.error;
|
||||
ws.close();
|
||||
}
|
||||
|
||||
if (ws.readyState !== WebSocket.OPEN) {
|
||||
break;
|
||||
}
|
||||
const buf = state.value;
|
||||
ws.send(buf);
|
||||
|
||||
onprogress(size);
|
||||
size += buf.length;
|
||||
state = await reader.read();
|
||||
while (ws.bufferedAmount > ECE_RECORD_SIZE * 2) {
|
||||
while (
|
||||
ws.bufferedAmount > ECE_RECORD_SIZE * 2 &&
|
||||
ws.readyState === WebSocket.OPEN &&
|
||||
!canceller.cancelled
|
||||
) {
|
||||
await delay();
|
||||
}
|
||||
}
|
||||
const footer = new Uint8Array([0]);
|
||||
ws.send(footer);
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(new Uint8Array([0])); //EOF
|
||||
}
|
||||
|
||||
await completedResponse;
|
||||
ws.close();
|
||||
uploadInfo.duration = Date.now() - start;
|
||||
return uploadInfo;
|
||||
} catch (e) {
|
||||
ws.close(4000);
|
||||
e.size = size;
|
||||
e.duration = Date.now() - start;
|
||||
throw e;
|
||||
} finally {
|
||||
if (![WebSocket.CLOSED, WebSocket.CLOSING].includes(ws.readyState)) {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +271,6 @@ export function uploadWs(
|
||||
|
||||
return {
|
||||
cancel: function() {
|
||||
canceller.error = new Error(0);
|
||||
canceller.cancelled = true;
|
||||
},
|
||||
|
||||
@@ -284,7 +310,7 @@ async function downloadS(id, keychain, signal) {
|
||||
return response.body;
|
||||
}
|
||||
|
||||
async function tryDownloadStream(id, keychain, signal, tries = 1) {
|
||||
async function tryDownloadStream(id, keychain, signal, tries = 2) {
|
||||
try {
|
||||
const result = await downloadS(id, keychain, signal);
|
||||
return result;
|
||||
@@ -306,18 +332,19 @@ export function downloadStream(id, keychain) {
|
||||
}
|
||||
return {
|
||||
cancel,
|
||||
result: tryDownloadStream(id, keychain, controller.signal, 2)
|
||||
result: tryDownloadStream(id, keychain, controller.signal)
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////
|
||||
|
||||
function download(id, keychain, onprogress, canceller) {
|
||||
async function download(id, keychain, onprogress, canceller) {
|
||||
const auth = await keychain.authHeader();
|
||||
const xhr = new XMLHttpRequest();
|
||||
canceller.oncancel = function() {
|
||||
xhr.abort();
|
||||
};
|
||||
return new Promise(async function(resolve, reject) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
xhr.addEventListener('loadend', function() {
|
||||
canceller.oncancel = function() {};
|
||||
const authHeader = xhr.getResponseHeader('WWW-Authenticate');
|
||||
@@ -337,7 +364,6 @@ function download(id, keychain, onprogress, canceller) {
|
||||
onprogress(event.loaded);
|
||||
}
|
||||
});
|
||||
const auth = await keychain.authHeader();
|
||||
xhr.open('get', getApiUrl(`/api/download/blob/${id}`));
|
||||
xhr.setRequestHeader('Authorization', auth);
|
||||
xhr.responseType = 'blob';
|
||||
@@ -346,7 +372,7 @@ function download(id, keychain, onprogress, canceller) {
|
||||
});
|
||||
}
|
||||
|
||||
async function tryDownload(id, keychain, onprogress, canceller, tries = 1) {
|
||||
async function tryDownload(id, keychain, onprogress, canceller, tries = 2) {
|
||||
try {
|
||||
const result = await download(id, keychain, onprogress, canceller);
|
||||
return result;
|
||||
@@ -367,7 +393,7 @@ export function downloadFile(id, keychain, onprogress) {
|
||||
}
|
||||
return {
|
||||
cancel,
|
||||
result: tryDownload(id, keychain, onprogress, canceller, 2)
|
||||
result: tryDownload(id, keychain, onprogress, canceller)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ async function polyfillStreams() {
|
||||
}
|
||||
|
||||
export default async function getCapabilities() {
|
||||
const serviceWorker =
|
||||
'serviceWorker' in navigator && browserName() !== 'edge';
|
||||
const browser = browserName();
|
||||
const serviceWorker = 'serviceWorker' in navigator && browser !== 'edge';
|
||||
let crypto = await checkCrypto();
|
||||
const nativeStreams = checkStreams();
|
||||
let polyStreams = false;
|
||||
@@ -97,13 +97,16 @@ export default async function getCapabilities() {
|
||||
window.matchMedia('(display-mode: standalone)').matches ||
|
||||
navigator.standalone;
|
||||
|
||||
const mobileFirefox =
|
||||
browser === 'firefox' && /mobile/i.test(navigator.userAgent);
|
||||
|
||||
return {
|
||||
account,
|
||||
crypto,
|
||||
serviceWorker,
|
||||
streamUpload: nativeStreams || polyStreams,
|
||||
streamDownload:
|
||||
nativeStreams && serviceWorker && browserName() !== 'safari',
|
||||
nativeStreams && serviceWorker && browser !== 'safari' && !mobileFirefox,
|
||||
multifile: nativeStreams || polyStreams,
|
||||
share,
|
||||
standalone
|
||||
|
||||
@@ -76,7 +76,7 @@ export default function(state, emitter) {
|
||||
state.storage.remove(ownedFile.id);
|
||||
await ownedFile.del();
|
||||
} catch (e) {
|
||||
state.raven.captureException(e);
|
||||
state.sentry.captureException(e);
|
||||
}
|
||||
render();
|
||||
});
|
||||
@@ -176,14 +176,17 @@ export default function(state, emitter) {
|
||||
} catch (err) {
|
||||
if (err.message === '0') {
|
||||
//cancelled. do nothing
|
||||
const duration = Date.now() - start;
|
||||
metrics.cancelledUpload(archive, duration);
|
||||
metrics.cancelledUpload(archive, err.duration);
|
||||
render();
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
state.raven.captureException(err);
|
||||
metrics.stoppedUpload(archive);
|
||||
state.sentry.withScope(scope => {
|
||||
scope.setExtra('duration', err.duration);
|
||||
scope.setExtra('size', err.size);
|
||||
state.sentry.captureException(err);
|
||||
});
|
||||
metrics.stoppedUpload(archive, err.duration);
|
||||
emitter.emit('pushState', '/error');
|
||||
}
|
||||
} finally {
|
||||
@@ -262,7 +265,12 @@ export default function(state, emitter) {
|
||||
state.transfer = null;
|
||||
const location = err.message === '404' ? '/404' : '/error';
|
||||
if (location === '/error') {
|
||||
state.raven.captureException(err);
|
||||
state.sentry.withScope(scope => {
|
||||
scope.setExtra('duration', err.duration);
|
||||
scope.setExtra('size', err.size);
|
||||
scope.setExtra('progress', err.progress);
|
||||
state.sentry.captureException(err);
|
||||
});
|
||||
const duration = Date.now() - start;
|
||||
metrics.stoppedDownload({
|
||||
size,
|
||||
|
||||
@@ -112,6 +112,7 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
|
||||
async downloadStream(noSave = false) {
|
||||
const start = Date.now();
|
||||
const onprogress = p => {
|
||||
this.progress = [p, this.fileInfo.size];
|
||||
this.emit('progress');
|
||||
@@ -153,9 +154,7 @@ export default class FileReceiver extends Nanobus {
|
||||
const downloadPath = `/api/download/${this.fileInfo.id}`;
|
||||
let downloadUrl = getApiUrl(downloadPath);
|
||||
if (downloadUrl === downloadPath) {
|
||||
downloadUrl = `${location.protocol}//${location.host}/api/download/${
|
||||
this.fileInfo.id
|
||||
}`;
|
||||
downloadUrl = `${location.protocol}//${location.host}${downloadPath}`;
|
||||
}
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
@@ -164,11 +163,29 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
|
||||
let prog = 0;
|
||||
let hangs = 0;
|
||||
while (prog < this.fileInfo.size) {
|
||||
const msg = await this.sendMessageToSw({
|
||||
request: 'progress',
|
||||
id: this.fileInfo.id
|
||||
});
|
||||
if (msg.progress === prog) {
|
||||
hangs++;
|
||||
} else {
|
||||
hangs = 0;
|
||||
}
|
||||
if (hangs > 30) {
|
||||
// TODO: On Chrome we don't get a cancel
|
||||
// signal so one is indistinguishable from
|
||||
// a hang. We may be able to detect
|
||||
// which end is hung in the service worker
|
||||
// to improve on this.
|
||||
const e = new Error('hung download');
|
||||
e.duration = Date.now() - start;
|
||||
e.size = this.fileInfo.size;
|
||||
e.progress = prog;
|
||||
throw e;
|
||||
}
|
||||
prog = msg.progress;
|
||||
onprogress(prog);
|
||||
await delay(1000);
|
||||
|
||||
@@ -44,7 +44,6 @@ export default class FileSender extends Nanobus {
|
||||
}
|
||||
|
||||
async upload(archive, bearerToken) {
|
||||
const start = Date.now();
|
||||
if (this.cancelled) {
|
||||
throw new Error(0);
|
||||
}
|
||||
@@ -76,7 +75,6 @@ export default class FileSender extends Nanobus {
|
||||
this.emit('progress'); // HACK to kick MS Edge
|
||||
try {
|
||||
const result = await this.uploadRequest.result;
|
||||
const time = Date.now() - start;
|
||||
this.msg = 'notifyUploadEncryptDone';
|
||||
this.uploadRequest = null;
|
||||
this.progress = [1, 1];
|
||||
@@ -87,8 +85,8 @@ export default class FileSender extends Nanobus {
|
||||
name: archive.name,
|
||||
size: archive.size,
|
||||
manifest: archive.manifest,
|
||||
time: time,
|
||||
speed: archive.size / (time / 1000),
|
||||
time: result.duration,
|
||||
speed: archive.size / (result.duration / 1000),
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + archive.timeLimit * 1000,
|
||||
secretKey: secretKey,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FluentBundle } from 'fluent';
|
||||
import { FluentBundle } from '@fluent/bundle';
|
||||
|
||||
function makeBundle(locale, ftl) {
|
||||
const bundle = new FluentBundle(locale, { useIsolating: false });
|
||||
@@ -10,9 +10,9 @@ export async function getTranslator(locale) {
|
||||
const bundles = [];
|
||||
const { default: en } = await import('../public/locales/en-US/send.ftl');
|
||||
if (locale !== 'en-US') {
|
||||
const {
|
||||
default: ftl
|
||||
} = await import(`../public/locales/${locale}/send.ftl`);
|
||||
const { default: ftl } = await import(
|
||||
`../public/locales/${locale}/send.ftl`
|
||||
);
|
||||
bundles.push(makeBundle(locale, ftl));
|
||||
}
|
||||
bundles.push(makeBundle('en-US', en));
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
@tailwind preflight;
|
||||
@tailwind base;
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
@tailwind components;
|
||||
|
||||
:not(input) {
|
||||
@@ -311,6 +316,7 @@ select {
|
||||
}
|
||||
|
||||
.signin {
|
||||
backface-visibility: hidden;
|
||||
border-radius: 6px;
|
||||
transition-property: transform, background-color;
|
||||
transition-duration: 250ms;
|
||||
|
||||
14
app/main.js
14
app/main.js
@@ -1,7 +1,7 @@
|
||||
/* global DEFAULTS LIMITS PREFS */
|
||||
import 'core-js';
|
||||
import 'fast-text-encoding'; // MS Edge support
|
||||
import 'fluent-intl-polyfill';
|
||||
import 'intl-pluralrules';
|
||||
import choo from 'choo';
|
||||
import nanotiming from 'nanotiming';
|
||||
import routes from './routes';
|
||||
@@ -12,15 +12,15 @@ import pasteManager from './pasteManager';
|
||||
import storage from './storage';
|
||||
import metrics from './metrics';
|
||||
import experiments from './experiments';
|
||||
import Raven from 'raven-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import './main.css';
|
||||
import User from './user';
|
||||
import { getTranslator } from './locale';
|
||||
import Archive from './archive';
|
||||
import { setTranslate, locale } from './utils';
|
||||
|
||||
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
||||
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
||||
if (navigator.doNotTrack !== '1' && window.SENTRY_CONFIG) {
|
||||
Sentry.init(window.SENTRY_CONFIG);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
@@ -47,6 +47,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
const translate = await getTranslator(locale());
|
||||
setTranslate(translate);
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
window.initialState = {
|
||||
LIMITS,
|
||||
DEFAULTS,
|
||||
@@ -55,13 +56,14 @@ if (process.env.NODE_ENV === 'production') {
|
||||
capabilities,
|
||||
translate,
|
||||
storage,
|
||||
raven: Raven,
|
||||
sentry: Sentry,
|
||||
user: new User(storage, LIMITS, window.AUTH_CONFIG),
|
||||
transfer: null,
|
||||
fileInfo: null
|
||||
};
|
||||
|
||||
const app = routes(choo());
|
||||
const app = routes(choo({ hash: true }));
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
window.app = app;
|
||||
app.use(experiments);
|
||||
app.use(metrics);
|
||||
|
||||
@@ -107,9 +107,10 @@ function completedUpload(archive, duration) {
|
||||
});
|
||||
}
|
||||
|
||||
function stoppedUpload(archive) {
|
||||
function stoppedUpload(archive, duration = 0) {
|
||||
return addEvent('client_upload', {
|
||||
download_limit: archive.dlimit,
|
||||
duration: sizeOrder(duration),
|
||||
file_count: archive.numFiles,
|
||||
password_protected: !!archive.password,
|
||||
size: sizeOrder(archive.size),
|
||||
|
||||
@@ -2,7 +2,7 @@ const choo = require('choo');
|
||||
const download = require('./ui/download');
|
||||
const body = require('./ui/body');
|
||||
|
||||
module.exports = function(app = choo()) {
|
||||
module.exports = function(app = choo({ hash: true })) {
|
||||
app.route('/', body(require('./ui/home')));
|
||||
app.route('/download/:id', body(download));
|
||||
app.route('/download/:id/:key', body(download));
|
||||
@@ -13,6 +13,7 @@ module.exports = function(app = choo()) {
|
||||
app.route('/oauth', function(state, emit) {
|
||||
emit('authenticate', state.query.code, state.query.state);
|
||||
});
|
||||
app.route('/login', body(require('./ui/home')));
|
||||
app.route('*', body(require('./ui/notFound')));
|
||||
return app;
|
||||
};
|
||||
|
||||
@@ -11,13 +11,14 @@ const map = new Map();
|
||||
const IMAGES = /.*\.(png|svg|jpg)$/;
|
||||
const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/;
|
||||
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
|
||||
const FONT = /\.woff2?$/;
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(precache());
|
||||
self.addEventListener('install', () => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(self.clients.claim());
|
||||
event.waitUntil(self.clients.claim().then(precache));
|
||||
});
|
||||
|
||||
async function decryptStream(id) {
|
||||
@@ -83,16 +84,28 @@ async function decryptStream(id) {
|
||||
}
|
||||
|
||||
async function precache() {
|
||||
try {
|
||||
await cleanCache();
|
||||
const cache = await caches.open(version);
|
||||
const images = assets.match(IMAGES);
|
||||
await cache.addAll(images);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// cache will get populated on demand
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanCache() {
|
||||
const oldCaches = await caches.keys();
|
||||
for (const c of oldCaches) {
|
||||
if (c !== version) {
|
||||
await caches.delete(c);
|
||||
}
|
||||
}
|
||||
const cache = await caches.open(version);
|
||||
const images = assets.match(IMAGES);
|
||||
await cache.addAll(images);
|
||||
return self.skipWaiting();
|
||||
}
|
||||
|
||||
function cacheable(url) {
|
||||
return VERSIONED_ASSET.test(url) || FONT.test(url);
|
||||
}
|
||||
|
||||
async function cachedOrFetched(req) {
|
||||
@@ -102,7 +115,7 @@ async function cachedOrFetched(req) {
|
||||
return cached;
|
||||
}
|
||||
const fetched = await fetch(req);
|
||||
if (fetched.ok && VERSIONED_ASSET.test(req.url)) {
|
||||
if (fetched.ok && cacheable(req.url)) {
|
||||
cache.put(req, fetched.clone());
|
||||
}
|
||||
return fetched;
|
||||
@@ -115,7 +128,7 @@ self.onfetch = event => {
|
||||
const dlmatch = DOWNLOAD_URL.exec(url.pathname);
|
||||
if (dlmatch) {
|
||||
event.respondWith(decryptStream(dlmatch[1]));
|
||||
} else if (VERSIONED_ASSET.test(url.pathname)) {
|
||||
} else if (cacheable(url.pathname)) {
|
||||
event.respondWith(cachedOrFetched(req));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global ReadableStream TransformStream */
|
||||
/* global TransformStream */
|
||||
|
||||
export function transformStream(readable, transformer, oncancel) {
|
||||
try {
|
||||
|
||||
@@ -85,7 +85,7 @@ class Account extends Component {
|
||||
/>
|
||||
<ul
|
||||
id="accountMenu"
|
||||
class="invisible list-reset absolute pin-t pin-r mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50"
|
||||
class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50"
|
||||
onblur="${e => this.hideMenu(e)}"
|
||||
>
|
||||
<li class="p-2 text-grey-dark">${user.email}</li>
|
||||
|
||||
@@ -120,7 +120,7 @@ function fileInfo(file, action) {
|
||||
function archiveInfo(archive, action) {
|
||||
return html`
|
||||
<p class="w-full flex items-center">
|
||||
<img class="mr-3 flex-no-shrink" src="${assets.get('blue_file.svg')}"/>
|
||||
<img class="mr-3 flex-shrink-0" src="${assets.get('blue_file.svg')}"/>
|
||||
<p class="flex-grow">
|
||||
<h1 class="text-base font-medium word-break-all">${archive.name}</h1>
|
||||
<div class="text-sm font-normal opacity-75 pt-1">${bytes(
|
||||
@@ -155,7 +155,7 @@ function archiveDetails(translate, archive) {
|
||||
num: archive.manifest.files.length
|
||||
})}
|
||||
</summary>
|
||||
${list(archive.manifest.files.map(f => fileInfo(f)), 'list-reset')}
|
||||
${list(archive.manifest.files.map(f => fileInfo(f)))}
|
||||
</details>
|
||||
`;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ module.exports = function(state, emit, archive) {
|
||||
html`
|
||||
<input
|
||||
type="image"
|
||||
class="self-start flex-no-shrink text-white hover:opacity-75 focus:outline"
|
||||
class="self-start flex-shrink-0 text-white hover:opacity-75 focus:outline"
|
||||
alt="${state.translate('deleteButtonHover')}"
|
||||
title="${state.translate('deleteButtonHover')}"
|
||||
src="${assets.get('close-16.svg')}"
|
||||
@@ -256,9 +256,7 @@ module.exports = function(state, emit, archive) {
|
||||
try {
|
||||
await navigator.share({
|
||||
title: state.translate('-send-brand'),
|
||||
text: `Download "${
|
||||
archive.name
|
||||
}" with Firefox Send: simple, safe file sharing`,
|
||||
text: `Download "${archive.name}" with Firefox Send: simple, safe file sharing`,
|
||||
//state.translate('shareMessage', { name }),
|
||||
url: archive.url
|
||||
});
|
||||
@@ -278,11 +276,11 @@ module.exports.wip = function(state, emit) {
|
||||
.map(f =>
|
||||
fileInfo(f, remove(f, state.translate('deleteButtonHover')))
|
||||
),
|
||||
'flex-shrink bg-grey-lightest rounded-t list-reset overflow-y-auto px-6 py-4 md:h-full md:max-h-half-screen',
|
||||
'flex-shrink bg-grey-lightest rounded-t overflow-y-auto px-6 py-4 md:h-full md:max-h-half-screen',
|
||||
'bg-white px-2 my-2 shadow-light rounded'
|
||||
)}
|
||||
<div
|
||||
class="flex-no-shrink flex-grow flex items-end p-4 bg-grey-lightest rounded-b mb-1 font-medium"
|
||||
class="flex-shrink-0 flex-grow flex items-end p-4 bg-grey-lightest rounded-b mb-1 font-medium"
|
||||
>
|
||||
<input
|
||||
id="file-upload"
|
||||
@@ -315,7 +313,7 @@ module.exports.wip = function(state, emit) {
|
||||
${expiryOptions(state, emit)} ${password(state, emit)}
|
||||
<button
|
||||
id="upload-btn"
|
||||
class="btn rounded-lg flex-no-shrink focus:outline"
|
||||
class="btn rounded-lg flex-shrink-0 focus:outline"
|
||||
title="${state.translate('uploadButton')}"
|
||||
onclick="${upload}"
|
||||
>
|
||||
@@ -509,7 +507,7 @@ module.exports.preview = function(state, emit) {
|
||||
</div>
|
||||
<button
|
||||
id="download-btn"
|
||||
class="btn rounded-lg mt-4 w-full flex-no-shrink focus:outline"
|
||||
class="btn rounded-lg mt-4 w-full flex-shrink-0 focus:outline"
|
||||
title="${state.translate('downloadButtonLabel')}"
|
||||
onclick=${download}
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = function(name, url) {
|
||||
<send-copy-dialog
|
||||
class="flex flex-col items-center text-center p-4 max-w-sm m-auto"
|
||||
>
|
||||
<h1 class="font-bold my-4">
|
||||
<h1 class="text-3xl font-bold my-4">
|
||||
${state.translate('notifyUploadEncryptDone')}
|
||||
</h1>
|
||||
<p class="font-normal leading-normal text-grey-darkest word-break-all">
|
||||
@@ -22,7 +22,7 @@ module.exports = function(name, url) {
|
||||
readonly="true"
|
||||
/>
|
||||
<button
|
||||
class="btn rounded-lg w-full flex-no-shrink focus:outline"
|
||||
class="btn rounded-lg w-full flex-shrink-0 focus:outline"
|
||||
onclick="${copy}"
|
||||
title="${state.translate('copyLinkButton')}"
|
||||
>
|
||||
|
||||
@@ -22,7 +22,9 @@ function downloading(state, emit) {
|
||||
<div
|
||||
class="flex flex-col w-full h-full items-center md:justify-center md:-mt-8"
|
||||
>
|
||||
<h1 class="mb-4">${state.translate('downloadingTitle')}</h1>
|
||||
<h1 class="text-3xl font-bold mb-4">
|
||||
${state.translate('downloadingTitle')}
|
||||
</h1>
|
||||
${archiveTile.downloading(state, emit)}
|
||||
</div>
|
||||
`;
|
||||
@@ -36,7 +38,9 @@ function preview(state, emit) {
|
||||
<div
|
||||
class="flex flex-col w-full max-w-md h-full mx-auto items-center justify-center"
|
||||
>
|
||||
<h1 class="mb-4">${state.translate('downloadTitle')}</h1>
|
||||
<h1 class="text-3xl font-bold mb-4">
|
||||
${state.translate('downloadTitle')}
|
||||
</h1>
|
||||
<p class="w-full text-grey-darkest text-center leading-normal">
|
||||
${state.translate('downloadDescription')}
|
||||
</p>
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = function(state) {
|
||||
id="download-complete"
|
||||
class="flex flex-col items-center justify-center h-full w-full bg-white p-2"
|
||||
>
|
||||
<h1 class="text-center font-bold my-2">
|
||||
<h1 class="text-center text-3xl font-bold my-2">
|
||||
${state.translate('downloadFinish')}
|
||||
</h1>
|
||||
<img src="${assets.get('completed.svg')}" class="my-12 h-48" />
|
||||
|
||||
@@ -8,7 +8,9 @@ module.exports = function(state, emit) {
|
||||
<div
|
||||
class="h-full w-full flex flex-col items-center justify-center bg-white py-8 max-w-md mx-auto"
|
||||
>
|
||||
<h1 class="mb-4">${state.translate('downloadTitle')}</h1>
|
||||
<h1 class="text-3xl font-bold mb-4">
|
||||
${state.translate('downloadTitle')}
|
||||
</h1>
|
||||
<p class="w-full mb-4 text-center text-grey-darkest leading-normal">
|
||||
${state.translate('downloadDescription')}
|
||||
</p>
|
||||
|
||||
@@ -9,7 +9,7 @@ module.exports = function(state, emit) {
|
||||
<section
|
||||
class="flex flex-col items-center justify-center h-full w-full p-6 md:p-8 overflow-hidden md:rounded-xl md:shadow-big"
|
||||
>
|
||||
<h1 class="text-center font-bold my-2">
|
||||
<h1 class="text-center text-3xl font-bold my-2">
|
||||
${state.translate('errorPageHeader')}
|
||||
</h1>
|
||||
<img class="my-12 h-48" src="${assets.get('error.svg')}" />
|
||||
|
||||
@@ -28,7 +28,7 @@ class Footer extends Component {
|
||||
Mozilla
|
||||
</a>
|
||||
<ul
|
||||
class="list-reset flex flex-col md:flex-row items-start md:items-center md:justify-end"
|
||||
class="flex flex-col md:flex-row items-start md:items-center md:justify-end"
|
||||
>
|
||||
<li class="m-2">
|
||||
<a href="https://www.mozilla.org/about/legal/terms/services/#send">
|
||||
|
||||
@@ -20,11 +20,7 @@ module.exports = function(state, emit) {
|
||||
const right =
|
||||
archives.length === 0
|
||||
? intro(state)
|
||||
: list(
|
||||
archives,
|
||||
'list-reset p-2 h-full overflow-y-auto w-full',
|
||||
'mb-4 w-full'
|
||||
);
|
||||
: list(archives, 'p-2 h-full overflow-y-auto w-full', 'mb-4 w-full');
|
||||
|
||||
return html`
|
||||
<main class="main">
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = function intro(state) {
|
||||
class="flex flex-col items-center justify-center bg-white px-6 md:py-0 py-6 mb-0 h-full w-full"
|
||||
>
|
||||
<div class="mt-12 flex flex-col h-full">
|
||||
<h1 class="font-bold md:pb-2">
|
||||
<h1 class="text-3xl font-bold md:pb-2">
|
||||
${state.translate('introTitle')}
|
||||
</h1>
|
||||
<p class="max-w-sm leading-loose mt-6 md:mt-2 md:pr-14">
|
||||
|
||||
@@ -8,7 +8,9 @@ module.exports = function(state, emit) {
|
||||
<div
|
||||
class="flex flex-col items-center bg-white m-4 px-6 py-8 border border-grey-light md:border-none md:px-12 md:py-16 shadow w-full md:h-full"
|
||||
>
|
||||
<h1 class="text-center">${state.translate('legalTitle')}</h1>
|
||||
<h1 class="text-center text-3xl font-bold">
|
||||
${state.translate('legalTitle')}
|
||||
</h1>
|
||||
<p class="mt-2">${state.translate('legalDateStamp')}</p>
|
||||
<div class="overflow-y-scroll py-8 px-12">
|
||||
<p class="leading-normal">
|
||||
|
||||
@@ -3,11 +3,11 @@ const html = require('choo/html');
|
||||
module.exports = function(state, emit) {
|
||||
return html`
|
||||
<send-modal
|
||||
class="absolute pin flex items-center justify-center overflow-hidden z-40 bg-white md:rounded-xl md:my-8"
|
||||
class="absolute inset-0 flex items-center justify-center overflow-hidden z-40 bg-white md:rounded-xl md:my-8"
|
||||
onclick="${close}"
|
||||
>
|
||||
<div
|
||||
class="h-full w-full max-h-screen absolute pin-t flex items-center justify-center"
|
||||
class="h-full w-full max-h-screen absolute top-0 flex items-center justify-center"
|
||||
>
|
||||
<div class="w-full" onclick="${e => e.stopPropagation()}">
|
||||
${state.modal(state, emit, close)}
|
||||
|
||||
@@ -8,7 +8,9 @@ module.exports = function(state, emit) {
|
||||
<div
|
||||
class="flex flex-col w-full max-w-md h-full mx-auto items-center justify-center"
|
||||
>
|
||||
<h1 class="mb-4">${state.translate('downloadTitle')}</h1>
|
||||
<h1 class="mb-4 text-3xl font-bold">${state.translate(
|
||||
'downloadTitle'
|
||||
)}</h1>
|
||||
<p
|
||||
class="w-full p-2 border border-yellow-light rounded md:w-4/5 text-orange-dark bg-yellow-lighter text-center leading-normal"
|
||||
>
|
||||
@@ -17,7 +19,7 @@ module.exports = function(state, emit) {
|
||||
<form class="md:w-128" onsubmit=${submit}>
|
||||
<fieldset class="border rounded p-4 my-4" onchange=${optionChanged}>
|
||||
<div class="flex items-center mb-2">
|
||||
<img class="mr-3 flex-no-shrink" src="${assets.get(
|
||||
<img class="mr-3 flex-shrink-0" src="${assets.get(
|
||||
'blue_file.svg'
|
||||
)}"/>
|
||||
<p class="flex-grow">
|
||||
@@ -49,7 +51,7 @@ module.exports = function(state, emit) {
|
||||
</div>
|
||||
</fieldset>
|
||||
<input
|
||||
class="btn rounded-lg w-full flex flex-no-shrink items-center justify-center"
|
||||
class="btn rounded-lg w-full flex flex-shrink-0 items-center justify-center"
|
||||
value="${state.translate('copyLinkButton')}"
|
||||
title="${state.translate('copyLinkButton')}"
|
||||
type="submit" />
|
||||
|
||||
@@ -9,7 +9,7 @@ module.exports = function(state, emit) {
|
||||
<section
|
||||
class="flex flex-col items-center justify-center h-full w-full p-6 md:p-8 overflow-hidden md:rounded-xl md:shadow-big"
|
||||
>
|
||||
<h1 class="text-center font-bold my-2">
|
||||
<h1 class="text-center text-3xl font-bold my-2">
|
||||
${state.translate('expiredTitle')}
|
||||
</h1>
|
||||
<img src="${assets.get('notFound.svg')}" class="my-12" />
|
||||
|
||||
@@ -4,9 +4,11 @@ module.exports = function(message) {
|
||||
return function(state, emit, close) {
|
||||
return html`
|
||||
<send-ok-dialog class="flex flex-col max-w-sm p-4 m-auto">
|
||||
<h2 class="text-center m-8 leading-normal">${message}</h2>
|
||||
<h2 class="text-center text-xl font-bold m-8 leading-normal">
|
||||
${message}
|
||||
</h2>
|
||||
<button
|
||||
class="btn rounded-lg w-full flex-no-shrink"
|
||||
class="btn rounded-lg w-full flex-shrink-0"
|
||||
onclick="${close}"
|
||||
title="${state.translate('okButton')}"
|
||||
>
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = function(name, url) {
|
||||
<send-share-dialog
|
||||
class="flex flex-col items-center text-center p-4 max-w-sm m-auto"
|
||||
>
|
||||
<h1 class="font-bold my-4">
|
||||
<h1 class="text-3xl font-bold my-4">
|
||||
${state.translate('notifyUploadEncryptDone')}
|
||||
</h1>
|
||||
<p class="font-normal leading-normal text-grey-darkest word-break-all">
|
||||
@@ -21,7 +21,7 @@ module.exports = function(name, url) {
|
||||
readonly="true"
|
||||
/>
|
||||
<button
|
||||
class="btn rounded-lg w-full flex-no-shrink focus:outline"
|
||||
class="btn rounded-lg w-full flex-shrink-0 focus:outline"
|
||||
onclick="${share}"
|
||||
title="${state.translate('shareLinkButton')}"
|
||||
>
|
||||
|
||||
@@ -14,9 +14,9 @@ module.exports = function(trigger) {
|
||||
>
|
||||
<img src="${assets.get('master-logo.svg')}" class="h-16 mt-1 mb-4" />
|
||||
<section
|
||||
class="flex flex-col flex-no-shrink self-center lg:mx-6 lg:max-w-xs"
|
||||
class="flex flex-col flex-shrink-0 self-center lg:mx-6 lg:max-w-xs"
|
||||
>
|
||||
<h1 class="font-bold text-center lg:text-left">
|
||||
<h1 class="text-3xl font-bold text-center lg:text-left">
|
||||
${state.translate('accountBenefitTitle')}
|
||||
</h1>
|
||||
<ul
|
||||
@@ -46,7 +46,7 @@ module.exports = function(trigger) {
|
||||
placeholder=${state.translate('emailPlaceholder')}
|
||||
/>
|
||||
<input
|
||||
class="btn rounded-lg w-full flex flex-no-shrink items-center justify-center"
|
||||
class="btn rounded-lg w-full flex flex-shrink-0 items-center justify-center"
|
||||
value="${state.translate('signInOnlyButton')}"
|
||||
title="${state.translate('signInOnlyButton')}"
|
||||
id="email-submit"
|
||||
|
||||
@@ -13,7 +13,7 @@ module.exports = function() {
|
||||
<send-survey-dialog
|
||||
class="flex flex-col items-center text-center p-4 max-w-sm m-auto"
|
||||
>
|
||||
<h1 class="font-bold my-4">
|
||||
<h1 class="text-3xl font-bold my-4">
|
||||
Tell us what you think.
|
||||
</h1>
|
||||
<p class="font-normal leading-normal text-grey-darkest px-4">
|
||||
@@ -21,7 +21,7 @@ module.exports = function() {
|
||||
it better.
|
||||
</p>
|
||||
<a
|
||||
class="btn rounded-lg w-full flex-no-shrink focus:outline my-5"
|
||||
class="btn rounded-lg w-full flex-shrink-0 focus:outline my-5"
|
||||
onclick="${() => emit('closeModal')}"
|
||||
title="Give feedback"
|
||||
href="${surveyUrl}"
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = function(state, emit) {
|
||||
<section
|
||||
class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border border-grey-light md:border-none md:px-12 md:py-16 shadow w-full md:h-full"
|
||||
>
|
||||
<h1 class="">${strings.header}</h1>
|
||||
<h1 class="text-3xl font-bold">${strings.header}</h1>
|
||||
<p class="mt-4 mb-8 max-w-md leading-normal">${strings.description}</p>
|
||||
${why}
|
||||
<a href="${url}" class="btn rounded-lg mt-8 px-8">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Custom Loaders
|
||||
|
||||
## Generate Asset Map
|
||||
## Android Index Plugin
|
||||
|
||||
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.
|
||||
Generates the `index.html` page for the native android client
|
||||
|
||||
## Version Plugin
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const genmap = require('../build/generate_asset_map');
|
||||
const genmap = require('./generate_asset_map');
|
||||
const isServer = typeof genmap === 'function';
|
||||
let prefix = '';
|
||||
let manifest = {};
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Common Code
|
||||
|
||||
This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`).
|
||||
This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`).
|
||||
|
||||
## Generate Asset Map
|
||||
|
||||
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.
|
||||
68
docs/deployment.md
Normal file
68
docs/deployment.md
Normal file
@@ -0,0 +1,68 @@
|
||||
## Requirements
|
||||
This document describes how to do a full deployment of Firefox Send on your own Linux server. You will need:
|
||||
|
||||
* A working (and ideally somewhat recent) installation of NodeJS and NPM
|
||||
* GIT
|
||||
* An Apache webserver
|
||||
* Optionally telnet, to be able to quickly check your installation
|
||||
|
||||
For Debian/Ubuntu systems this probably just means something like this:
|
||||
|
||||
* apt install git apache2 nodejs npm telnet
|
||||
|
||||
## Building
|
||||
* We assume an already configured virtual-host on your webserver with an existing empty htdocs folder
|
||||
* First, remove that htdocs folder - we will replace it with Firefox Send's version now
|
||||
* git clone https://github.com/mozilla/send.git htdocs
|
||||
* Make now sure you are NOT root but rather the user your webserver is serving files under (e.g. "su www-data" or whoever the owner of your htdocs folder is)
|
||||
* npm install
|
||||
* npm run build
|
||||
|
||||
## Running
|
||||
To have a permanently running version of Firefox Send as a background process:
|
||||
|
||||
* Create a file "run.sh" with:
|
||||
```
|
||||
#!/bin/bash
|
||||
nohup su www-data -c "npm run prod" 2>/dev/null &
|
||||
```
|
||||
* chmod +x run.sh
|
||||
* ./run.sh
|
||||
|
||||
Now the Firefox Send backend should be running on port 1443. You can check with:
|
||||
* telnet localhost 1443
|
||||
|
||||
## Reverse Proxy
|
||||
Of course, we don't want to expose the service on port 1443. Instead we want our normal webserver to forward all requests to Firefox send ("Reverse proxy").
|
||||
|
||||
# Apache webserver
|
||||
|
||||
* a2enmod proxy
|
||||
* a2enmod proxy_http
|
||||
* a2enmod proxy_wstunnel
|
||||
|
||||
In your Apache virtual host configuration file, insert this:
|
||||
|
||||
```
|
||||
# Enable rewrite engine
|
||||
RewriteEngine on
|
||||
|
||||
# Make sure the original domain name is forwarded to Send
|
||||
# Otherwise the generated URLs will be wrong
|
||||
ProxyPreserveHost on
|
||||
|
||||
# Make sure the generated URL is https://
|
||||
RequestHeader set X-Forwarded-Proto https
|
||||
|
||||
# If it's a normal file (e.g. PNG, CSS) just return it
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteRule .* - [L]
|
||||
|
||||
# If it's a websocket connection, redirect it to a Send WS connection
|
||||
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
||||
RewriteRule /(.*) ws://127.0.0.1:1443/$1 [P,L]
|
||||
|
||||
# Otherwise redirect it to a normal HTTP connection
|
||||
RewriteRule ^/(.*)$ http://127.0.0.1:1443/$1 [P,QSA]
|
||||
ProxyPassReverse "/" "http://127.0.0.1:1443"
|
||||
```
|
||||
@@ -1,13 +1,6 @@
|
||||
## Setup
|
||||
|
||||
Before building the Docker image, you must build the production assets:
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
Then you can run either `docker build` or `docker-compose up`.
|
||||
|
||||
Run `docker build -t send:latest .` to create an image or `docker-compose up` to run a full testable stack. *We don't recommend using docker-compose for production.*
|
||||
|
||||
## Environment variables:
|
||||
|
||||
|
||||
6159
package-lock.json
generated
6159
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
118
package.json
118
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "firefox-send",
|
||||
"description": "File Sharing Experiment",
|
||||
"version": "3.0.12",
|
||||
"version": "3.0.19",
|
||||
"author": "Mozilla (https://mozilla.org)",
|
||||
"repository": "mozilla/send",
|
||||
"homepage": "https://github.com/mozilla/send/",
|
||||
@@ -35,7 +35,8 @@
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"pre-push": "npm test",
|
||||
"post-merge": "npm install"
|
||||
"post-merge": "npm install",
|
||||
"post-checkout": "scripts/sync-npm-dependencies.sh"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -57,68 +58,69 @@
|
||||
"cache": true
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
"node": ">=10.0.0 <11.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.4",
|
||||
"@babel/core": "^7.6.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"@babel/preset-env": "^7.6.0",
|
||||
"@dannycoates/webcrypto-liner": "^0.1.37",
|
||||
"@fullhuman/postcss-purgecss": "^1.2.0",
|
||||
"@fullhuman/postcss-purgecss": "^1.3.0",
|
||||
"@mattiasbuelens/web-streams-polyfill": "0.2.1",
|
||||
"@sentry/browser": "^5.6.3",
|
||||
"asmcrypto.js": "^0.22.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-istanbul": "^5.1.4",
|
||||
"base64-js": "^1.3.0",
|
||||
"babel-plugin-istanbul": "^5.2.0",
|
||||
"base64-js": "^1.3.1",
|
||||
"content-disposition": "^0.5.3",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"core-js": "^3.1.3",
|
||||
"copy-webpack-plugin": "^5.0.4",
|
||||
"core-js": "^3.2.1",
|
||||
"crc": "^3.8.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^2.1.1",
|
||||
"cross-env": "^5.2.1",
|
||||
"css-loader": "^3.2.0",
|
||||
"css-mqpacker": "^7.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-mocha": "^5.3.0",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint": "^6.4.0",
|
||||
"eslint-config-prettier": "^6.3.0",
|
||||
"eslint-plugin-mocha": "^6.1.1",
|
||||
"eslint-plugin-node": "^9.2.0",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"expose-loader": "^0.7.5",
|
||||
"extract-loader": "^3.1.0",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"fast-text-encoding": "^1.0.0",
|
||||
"file-loader": "^3.0.1",
|
||||
"fluent-intl-polyfill": "^0.1.0",
|
||||
"file-loader": "^4.2.0",
|
||||
"git-rev-sync": "^1.12.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"http_ece": "^1.1.0",
|
||||
"husky": "^2.3.0",
|
||||
"lint-staged": "^8.1.7",
|
||||
"mocha": "^6.1.4",
|
||||
"husky": "^3.0.5",
|
||||
"intl-pluralrules": "^1.0.3",
|
||||
"lint-staged": "^9.3.0",
|
||||
"mocha": "^6.2.0",
|
||||
"morgan": "^1.9.1",
|
||||
"nanobus": "^4.4.0",
|
||||
"nanohtml": "^1.6.2",
|
||||
"nanohtml": "^1.8.1",
|
||||
"nanotiming": "^7.3.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "^14.1.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.6.0",
|
||||
"prettier": "^1.17.1",
|
||||
"proxyquire": "^2.1.0",
|
||||
"puppeteer": "^1.17.0",
|
||||
"raven-js": "^3.27.1",
|
||||
"raw-loader": "^2.0.0",
|
||||
"redis-mock": "^0.43.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"prettier": "^1.18.2",
|
||||
"proxyquire": "^2.1.3",
|
||||
"puppeteer": "^1.20.0",
|
||||
"raw-loader": "^3.1.0",
|
||||
"redis-mock": "^0.46.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"script-loader": "^0.7.2",
|
||||
"sinon": "^7.3.2",
|
||||
"sinon": "^7.5.0",
|
||||
"string-hash": "^1.1.3",
|
||||
"stylelint": "^10.0.1",
|
||||
"stylelint": "^10.1.0",
|
||||
"stylelint-config-standard": "^18.3.0",
|
||||
"stylelint-no-unsupported-browser-features": "^3.0.2",
|
||||
"svgo": "^1.2.2",
|
||||
"svgo-loader": "^2.2.0",
|
||||
"tailwindcss": "^0.7.4",
|
||||
"svgo": "^1.3.0",
|
||||
"svgo-loader": "^2.2.1",
|
||||
"tailwindcss": "^1.1.2",
|
||||
"val-loader": "^1.1.1",
|
||||
"wdio-docker-service": "^1.4.2",
|
||||
"wdio-dot-reporter": "0.0.10",
|
||||
@@ -128,39 +130,41 @@
|
||||
"wdio-selenium-standalone-service": "0.0.12",
|
||||
"wdio-spec-reporter": "^0.1.5",
|
||||
"webdriverio": "^4.14.4",
|
||||
"webpack": "^4.32.2",
|
||||
"webpack-cli": "^3.3.2",
|
||||
"webpack-dev-middleware": "^3.7.0",
|
||||
"webpack-dev-server": "^3.4.1",
|
||||
"webpack-manifest-plugin": "^2.0.4",
|
||||
"webpack": "4.38.0",
|
||||
"webpack-cli": "^3.3.9",
|
||||
"webpack-dev-middleware": "^3.7.1",
|
||||
"webpack-dev-server": "^3.8.1",
|
||||
"webpack-manifest-plugin": "^2.1.0",
|
||||
"webpack-unassert-loader": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google-cloud/storage": "^2.5.0",
|
||||
"aws-sdk": "^2.465.0",
|
||||
"@dannycoates/express-ws": "^5.0.3",
|
||||
"@fluent/bundle": "^0.13.0",
|
||||
"@fluent/langneg": "^0.3.0",
|
||||
"@google-cloud/storage": "^3.3.0",
|
||||
"@sentry/node": "^5.6.2",
|
||||
"aws-sdk": "^2.533.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"choo": "^6.13.3",
|
||||
"choo": "^7.0.0",
|
||||
"cldr-core": "^35.1.0",
|
||||
"convict": "^4.4.1",
|
||||
"configstore": "github:dannycoates/configstore#master",
|
||||
"convict": "^5.1.0",
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "github:dannycoates/express-ws",
|
||||
"fluent": "^0.12.0",
|
||||
"fluent-langneg": "^0.1.1",
|
||||
"fxa-geodb": "^1.0.4",
|
||||
"helmet": "^3.18.0",
|
||||
"helmet": "^3.21.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mozlog": "^2.2.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"raven": "^2.6.4",
|
||||
"redis": "^2.8.0",
|
||||
"selenium-standalone": "^6.15.6",
|
||||
"ua-parser-js": "^0.7.19",
|
||||
"websocket-stream": "^5.5.0"
|
||||
"ua-parser-js": "^0.7.20"
|
||||
},
|
||||
"availableLanguages": [
|
||||
"en-US",
|
||||
"ar",
|
||||
"ast",
|
||||
"bn-BD",
|
||||
"bn",
|
||||
"br",
|
||||
"ca",
|
||||
"cak",
|
||||
"cs",
|
||||
@@ -175,9 +179,12 @@
|
||||
"es-CL",
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"et",
|
||||
"eu",
|
||||
"fi",
|
||||
"fr",
|
||||
"fy-NL",
|
||||
"he",
|
||||
"hr",
|
||||
"hsb",
|
||||
"hu",
|
||||
@@ -189,8 +196,12 @@
|
||||
"kab",
|
||||
"ko",
|
||||
"lt",
|
||||
"ml",
|
||||
"nb-NO",
|
||||
"nl",
|
||||
"nn-NO",
|
||||
"oc",
|
||||
"pa-IN",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
@@ -200,10 +211,13 @@
|
||||
"sl",
|
||||
"sq",
|
||||
"sr",
|
||||
"su",
|
||||
"sv-SE",
|
||||
"th",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zgh",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@ class TailwindExtractor {
|
||||
|
||||
const options = {
|
||||
plugins: [
|
||||
require('tailwindcss')('./tailwind.js'),
|
||||
require('tailwindcss')('./tailwind.config.js'),
|
||||
require('postcss-preset-env')
|
||||
]
|
||||
};
|
||||
|
||||
@@ -182,3 +182,5 @@ shareLinkDescription = شارِك الرابط الذي يصل إلى الملف
|
||||
shareLinkButton = شارِك الرابط
|
||||
# $name is the name of the file
|
||||
shareMessage = نزِّل ”{ $name }“ عبر { -send-brand }: خدمة لمشاركة الملفات بلا عناء وبخصوصية تامة
|
||||
trailheadPromo = يمكنك حماية خصوصيتك، طبعا. انضم إلى فَيَرفُكس.
|
||||
learnMore = اطّلع على المزيد.
|
||||
|
||||
@@ -126,7 +126,7 @@ addPassword = পাসওয়ার্ড দ্বারা সুরক্ষ
|
||||
emailPlaceholder = আপনার ইমেইল দিন
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = সর্বোচ্চ { $size } আকারের ফাইল প্রেরণ করতে সাইন ইন করুন
|
||||
signInButton = সাইন ইন/আপ
|
||||
signInOnlyButton = সাইন ইন
|
||||
accountBenefitTitle = { -firefox } অ্যাকাউন্ট তৈরি অথবা সাইন ইন করুন
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = সর্বোচ্চ { $size } আকারের ফাইল শেয়ার করুন
|
||||
@@ -145,3 +145,11 @@ noStreamsWarning = এই ব্রাউজার এতো বড় একট
|
||||
noStreamsOptionCopy = অন্য ব্রাউজারে খুলতে লিঙ্ক অনুলিপি করুন
|
||||
noStreamsOptionFirefox = আমাদের জনপ্রিয় ব্রাউজার ব্যবহার করুন
|
||||
noStreamsOptionDownload = এই ব্রাউজার ব্যবহার অব্যহত রাখুন
|
||||
downloadFirefoxPromo = { -send-short-brand } আপনারদের জন্য নিয়ে এসেছে একেবারে নতুন { -firefox }।
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = আপনার ফাইলে লিঙ্ক শেয়ার করুন:
|
||||
shareLinkButton = লিঙ্ক শেয়ার করুন
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand } এর মাধ্যমে "{ $name }" ডাউনলোড করুন: সরল, নিরাপদ ফাইল শেয়ারিং
|
||||
trailheadPromo = আপনার গোপনীয়তা রক্ষা করার একটি উপায় আছে। Firefox এ যোগ দিন।
|
||||
learnMore = আরও জানুন।
|
||||
@@ -196,5 +196,5 @@ shareLinkDescription = Sdílet odkaz na soubor:
|
||||
shareLinkButton = Sdílet odkaz
|
||||
# $name is the name of the file
|
||||
shareMessage = Stáhněte si soubor „{ $name }“ s { -send-brand(case: "ins") } - jednoduché a bezpečné sdílení souborů
|
||||
trailheadPromo = Existuje snadný způsob pro ochranu vašeho soukromí. Používejte Firefox.
|
||||
trailheadPromo = Existuje způsob, jak ochránit své soukromí. Používejte Firefox.
|
||||
learnMore = Zjistit více.
|
||||
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = Del linket til din fil:
|
||||
shareLinkButton = Del link
|
||||
# $name is the name of the file
|
||||
shareMessage = Hent { $name } med { -send-brand } - simpel og sikker fildeling
|
||||
trailheadPromo = Beskyt dine digitale rettigheder. Slut dig til Firefox.
|
||||
learnMore = Læs mere.
|
||||
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = Share the link to your file:
|
||||
shareLinkButton = Share link
|
||||
# $name is the name of the file
|
||||
shareMessage = Download “{ $name }” with { -send-brand }: simple, safe file sharing
|
||||
trailheadPromo = There is a way to protect your privacy. Join Firefox.
|
||||
learnMore = Learn more.
|
||||
|
||||
@@ -126,7 +126,7 @@ addPassword = Protegido con contraseña
|
||||
emailPlaceholder = Ingresa tu correo electrónico
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Iniciar sesión para enviar hasta { $size }
|
||||
signInButton = Iniciar sesión/registrarse
|
||||
signInOnlyButton = Iniciar sesión
|
||||
accountBenefitTitle = Crear una cuenta de { -firefox } o iniciar sesión
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Compartir archivos de hasta { $size }
|
||||
@@ -145,3 +145,11 @@ noStreamsWarning = Puede que este navegador no pueda descifrar un archivo tan gr
|
||||
noStreamsOptionCopy = Copiar el enlace para abrir en otro navegador
|
||||
noStreamsOptionFirefox = Prueba nuestro navegador favorito
|
||||
noStreamsOptionDownload = Continuar con este navegador
|
||||
downloadFirefoxPromo = { -send-short-brand } te lo ofrece el nuevo { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Comparte el enlace a tu archivo:
|
||||
shareLinkButton = Enlace para compartir
|
||||
# $name is the name of the file
|
||||
shareMessage = Descarga «{ $name }» con { -send-brand }: es sencillo y seguro
|
||||
trailheadPromo = Existe una forma de proteger tu privacidad. Únete a Firefox.
|
||||
learnMore = Saber más.
|
||||
|
||||
@@ -23,7 +23,7 @@ fileSizeProgress = ({ $totalSize } / { $partialSize })
|
||||
sendYourFilesLink = Probatu Firefox Send
|
||||
errorPageHeader = Zerbait gaizki joan da!
|
||||
fileTooBig = Fitxategia handiegia da kargatzeko. { $size } baino txikiagoa izan behar du.
|
||||
linkExpiredAlt = Lotura iraungita
|
||||
linkExpiredAlt = Lotura iraungi da
|
||||
notSupportedHeader = Zure nabigatzailea ez da onartzen.
|
||||
notSupportedLink = Zergatik ez da nire nabigatzailea onartzen?
|
||||
notSupportedOutdatedDetail = Zoritxarrez Firefox bertsio honek ez du Firefox Send-ek behar duen web teknologia onartzen. Zure nabigatzailea eguneratu behar duzu.
|
||||
@@ -50,10 +50,34 @@ passwordSetError = Pasahitz hau ezin da ezarri
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = Send
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Partekatu fitxategiak modu sinple eta pribatuan
|
||||
introDescription = { -send-brand } tresna fitxategiak partekatzeko da, muturretik muturrera zifratuta eta automatikoki iraungitzen diren loturekin. Hortaz, partekatzen duzuna pribatua izango da eta ziur egon zaitezke zure fitxategiak ez direla online egongo betirako.
|
||||
notifyUploadEncryptDone = Zure fitxategia zifratuta eta bidaltzeko prest dago
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = { $downloadCount } edo { $timespan } ondoren iraungiko da
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] minutu 1
|
||||
*[other] { $num } minutu
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] egun 1
|
||||
*[other] { $num } egun
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] aste 1
|
||||
*[other] { $num } aste
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] fitxategi 1
|
||||
*[other] { $num } fitxategi
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
@@ -64,9 +88,33 @@ mb = MB
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Tamaina guztira: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Kopiatu fitxategia partekatzeko lotura:
|
||||
copyLinkButton = Kopiatu lotura
|
||||
downloadTitle = Deskargatu fitxategiak
|
||||
downloadDescription = { -send-brand } bidez partekatu da fitxategia muturretik muturrera zifratuta eta automatikoki iraungitzen den lotura batekin.
|
||||
trySendDescription = Probatu { -send-brand } fitxategiak partekatzeko modu sinple eta segururako.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Soilik fitxategi bakarra igo daiteke aldi berean.
|
||||
*[other] Soilik { $count } fitxategi igo daitezke aldi berean.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Soilik artxibo bakarra onartzen da.
|
||||
*[other] Soilik { $count } artxibo onartzen dira.
|
||||
}
|
||||
expiredTitle = Lotura hau iraungi da.
|
||||
notSupportedDescription = { -send-brand } ez da nabigatzaile honetan ibiliko. { -send-short-brand } hobeto dabil { -firefox }(r)en azken bertsioarekin; halaber, nabigatzaile gehienen azken bertsioarekin ibiliko da.
|
||||
downloadFirefox = Deskargatu { -firefox }
|
||||
legalTitle = { -send-short-brand } pribatutasun-oharra
|
||||
legalDateStamp = 1.0 bertsioa, 2019ko martxoaren 12koa.
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }e { $hours }h { $minutes }m
|
||||
addFilesButton = Hautatu igotzeko fitxategiak
|
||||
uploadButton = Igo
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
@@ -76,8 +124,32 @@ dragAndDropFiles = Arrastatu eta jaregin fitxategiak
|
||||
orClickWithSize = edo egin klik { $size } arte igotzeko
|
||||
addPassword = Babestu pasahitzarekin
|
||||
emailPlaceholder = Idatzi zure helbide elektronikoa
|
||||
signInButton = Hasi saioa/eman izena
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Hasi saioa { $size } arte bidaltzeko
|
||||
signInOnlyButton = Hasi saioa
|
||||
accountBenefitTitle = Sortu { -firefox } kontu bat edo hasi saioa
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Partekatu { $size } arteko fitxategiak
|
||||
accountBenefitDownloadCount = Partekatu fitxategiak jende gehiagorekin
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Utzi loturak erabilgarri egun batez
|
||||
*[other] Utzi loturak erabilgarri { $count } egunez
|
||||
}
|
||||
accountBenefitSync = Kudeatu partekatutako fitxategiak edozein gailutatik
|
||||
accountBenefitMoz = { -mozilla }ren beste zerbitzuei buruzko argibide gehiago
|
||||
signOut = Amaitu saioa
|
||||
okButton = Ados
|
||||
downloadingTitle = Deskargatzen
|
||||
noStreamsWarning = Baliteke nabigatzailea gai ez izatea horrelako tamaina handiko fitxategiak deszifratzeko.
|
||||
noStreamsOptionCopy = Kopiatu lotura beste nabigatzaile batean irekitzeko
|
||||
noStreamsOptionFirefox = Probatu gure nabigatzaile gogokoena
|
||||
noStreamsOptionDownload = Jarraitu nabigatzaile honekin
|
||||
downloadFirefoxPromo = Erabat berritutako { -firefox }(e)k eskaintzen dizu { -send-short-brand }
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Partekatu zure fitxategirako lotura:
|
||||
shareLinkButton = Partekatu lotura
|
||||
# $name is the name of the file
|
||||
shareMessage = Deskargatu "{ $name }" { -send-brand } erabiliz: fitxategi-partekatze sinple eta segurua
|
||||
trailheadPromo = Badago zure pribatutasuna babesteko modua. Egizu bat Firefoxekin.
|
||||
learnMore = Argibide gehiago.
|
||||
|
||||
@@ -1,31 +1,9 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = آزمایش وب
|
||||
siteFeedback = بازخورد
|
||||
uploadPageHeader = اشتراکگذاری پروندهها، رمزنگاری شده و خصوصی
|
||||
uploadPageExplainer = پرونده های خود را به صورت ایمن، خصوصی و رمزنگاری شده با تعیین تاریخ انقضا خودکار ارسال کنید تا اطمینان پیدا کنید چیزهای شما همیشه آنلاین باقی نماند.
|
||||
uploadPageLearnMore = بیشتر بدانید
|
||||
uploadPageDropMessage = برای شروع بارگذاری پروندههای خود را اینجا بیاندازید
|
||||
uploadPageSizeMessage = برای بیشترین قابلیت اطمینان، بهتر است که پروندهتان کمتر از ۱ گیگابایت باشد
|
||||
uploadPageBrowseButton = یک پرونده را از روی کامپیوتر خود انتخاب کنید
|
||||
uploadPageBrowseButton1 = یک پرونده را برای بارگذاری انتخاب کنید
|
||||
uploadPageMultipleFilesAlert = بارگذاری چندین پرونده یا یک پوشه در حال حاضر پشتیبانی نمیشود.
|
||||
uploadPageBrowseButtonTitle = بارگذاری پرونده
|
||||
uploadingPageProgress = در حال بارگذاری پرونده { $filename } ({ $size })
|
||||
importingFile = در حال وارد کردن…
|
||||
verifyingFile = در حال تایید…
|
||||
encryptingFile = در حال رمزنگاری…
|
||||
decryptingFile = در حال رمزگشایی…
|
||||
notifyUploadDone = بارگذاری شما پایان یافت.
|
||||
uploadingPageMessage = به محض بارگذاری پرونده شما قادر خواهید بود برای آن گزینه انقضا تعیین کنید.
|
||||
uploadingPageCancel = لغو بارگذاری
|
||||
uploadCancelNotification = بارگذاری شما لغو شد
|
||||
uploadingPageLargeFileMessage = پرونده بزرگ است و ممکن است بارگذاری آن مدتی طول بکشد. محکم بشینید!
|
||||
uploadingFileNotification = هر وقت بارگذاری تمام شد به من اطلاع بده.
|
||||
uploadSuccessConfirmHeader = آماده برای ارسال
|
||||
uploadSvgAlt = بارگذاری
|
||||
uploadSuccessTimingHeader = پیوند به پرونده شما بعد از ۱ بار دانلود یا ۲۴ ساعت حذف خواهد شد.
|
||||
expireInfo = این پیوند به فایل شما پس از { $downloadCount } یا { $timespan } منقضی خواهد شد.
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] ۱ بارگیری
|
||||
@@ -36,76 +14,26 @@ timespanHours =
|
||||
[one] ۱ ساعت
|
||||
*[other] { $num } ساعت
|
||||
}
|
||||
copyUrlFormLabelWithName = برای ارسال پرونده پیوند آن را رونوشت و به اشتراک بگذارید: { $filename }
|
||||
copyUrlFormButton = رونوشت به کلیپبورد
|
||||
copiedUrl = رونوشت شد!
|
||||
deleteFileButton = حذف پرونده
|
||||
sendAnotherFileLink = ارسال پرونده دیگر
|
||||
# Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = دریافت
|
||||
downloadsFileList = دریافتها
|
||||
# Used as header in a column indicating the amount of time left before a
|
||||
# download link expires (e.g. "10h 5m")
|
||||
timeFileList = زمان
|
||||
# Used as header in a column indicating the number of times a file has been
|
||||
# downloaded
|
||||
downloadFileName = بارگیری { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = گذرواژه را وارد کنید
|
||||
unlockInputPlaceholder = گذرواژه
|
||||
unlockButtonLabel = باز کردن
|
||||
downloadFileTitle = دریافت پروندهٔ رمزنگاری شده
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = دوست شما درحال ارسال پرونده ای به وسیله Firefox Send است، این سرویس این امکان را به شما میدهد تا پروندههای خود را به صورت ایمن،خصوصی و رمزنگاری شده به همراه پیوند انقضا خودکار همرسانی کنید تا اطمینان حاصل کنید چیزهای شما برای همیشه آنلاین باقی نخواهد ماند.
|
||||
# Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = بارگیری
|
||||
downloadNotification = بارگیری شما کامل شد.
|
||||
downloadFinish = بارگیری کامل شد
|
||||
# This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } از { $totalSize })
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox Send را امتحان کنید
|
||||
downloadingPageProgress = دریافت { $filename } ({ $size })
|
||||
downloadingPageMessage = لطفا این زبانه را باز بگذارید در حالی که ما فایل شما را دریافت میکنیم و کدگذاری میکنیم.
|
||||
errorAltText = خطا در بارگذاری
|
||||
errorPageHeader = چیزی دچار اشکال شده است!
|
||||
errorPageMessage = خطایی در هنگام بارگذاری پرونده شما رخ داده است.
|
||||
errorPageLink = پرونده دیگری ارسال کنید.
|
||||
fileTooBig = این پرونده بسیار حجیم است. حجم آن میبایستی کم تر { $size } باشد.
|
||||
linkExpiredAlt = پیوند منقضی شده است
|
||||
expiredPageHeader = پیوند منقضی شده است یا در از همان ابتدا وجود نداشته است!
|
||||
notSupportedHeader = مرورگر شما پشتیبانی نمیکند.
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = متاسفانه این مرورگر این تکنولوژی وب را که به Firefox Send قدرت میبخشد را پشتیبانی نمیکند. شما بایستی مرورگری دیگری را امتحان کنید. پیشنهاد ما به شما فایرفاکس است !
|
||||
notSupportedLink = چرا مرورگر من پشتیبانی نمیکند؟
|
||||
notSupportedOutdatedDetail = متاسفانه این نسخه از فایرفاکس این تکنولوژی وب که به Firefox Send قدرت میبخشد را پشتیبانی نمیکند. شما نیاز دارید تا مرورگر خود را بروز کنید.
|
||||
updateFirefox = بروزرسانی فایرفاکس
|
||||
downloadFirefoxButtonSub = دریافت رایگان
|
||||
uploadedFile = پرونده
|
||||
copyFileList = رونوشت از نشانی
|
||||
# expiryFileList is used as a column header
|
||||
expiryFileList = زمان انقضا
|
||||
deleteFileList = حذف
|
||||
nevermindButton = بیخیال
|
||||
legalHeader = شرایط و حریمخصوصی
|
||||
legalNoticeTestPilot = Firefox Send در حال حاضر در نسخه آزمایشی خود به صورت میدهد و تحت عنوان خلبان آموزشی <a>شرایط و خدمات</a> و <a>موارد حریم خصوصی </a> کار میکند. شما میتوانید اطلاعات بیشتر در مورد این آزمایش و اطلاعات که ذخیره میکنید را از <a> اینجا </a> کسب کنید.
|
||||
legalNoticeMozilla = استفاده از Firefox Send همچنین منصوب به موزیلا است. <a>پایگاه اینترنتی نکات حریم شخصی </a> و <a> پایگاه اطلاع رسانی شرایط خدمات و استفاده </a>.
|
||||
deletePopupText = حذف این پرونده؟
|
||||
deletePopupYes = بله
|
||||
deletePopupCancel = انصراف
|
||||
deleteButtonHover = حذف
|
||||
copyUrlHover = رونوشت از نشانی
|
||||
footerLinkLegal = ملاحظات حقوقی
|
||||
# Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = درباره Test Pilot
|
||||
footerLinkPrivacy = حریمخصوصی
|
||||
footerLinkTerms = شرایط
|
||||
footerLinkCookies = کوکیها
|
||||
requirePasswordCheckbox = دریافت این پرونده نیاز به گذرواژه دارد
|
||||
addPasswordButton = افزودن گذرواژه
|
||||
changePasswordButton = تغییر
|
||||
passwordTryAgain = کلمه عبور اشتباه است. مجدد تلاش کنید.
|
||||
reportIPInfringement = گزارش تخلف IP
|
||||
javascriptRequired = Firefox Send نیازمند جاوااسکریپت است
|
||||
whyJavascript = چرا Firefox Send جاوااسکریپت لازم داد؟
|
||||
enableJavascript = لطفا جاوااسکریپت را فعال کنید و مجددا تلاش کنید.
|
||||
@@ -113,9 +41,26 @@ enableJavascript = لطفا جاوااسکریپت را فعال کنید و م
|
||||
expiresHoursMinutes = { $hours }ساعت { $minutes }دقیقه
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes } دقیقه
|
||||
# A short status message shown when a password is successfully set
|
||||
passwordIsSet = گذرواژه تنظیم شد
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = حداکثر اندازهٔ گذرواژه: { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = امکان ثبت این گذواژه نیست
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = ارسال
|
||||
-firefox = فایرفاکس
|
||||
-mozilla = موزیلا
|
||||
introTitle = اشتراکگذاری ساده و خصوصیِ پروندهها
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
kb = KB
|
||||
# mebibyte abbreviation
|
||||
mb = MB
|
||||
# gibibyte abbreviation
|
||||
gb = GB
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = حجم کل: { $size }
|
||||
|
||||
@@ -1,66 +1,158 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = ניסוי אינטרנט
|
||||
siteFeedback = משוב
|
||||
uploadPageHeader = שיתוף קבצים פרטי, מוצפן
|
||||
uploadPageExplainer = לשלוח קבצים דרך קישור בטוח, פרטי ומוצפן שפג אוטומטית, כדי לוודא שהתכנים הפרטיים שלך לא יהיו ברשת לנצח.
|
||||
uploadPageLearnMore = מידע נוסף
|
||||
uploadPageDropMessage = יש לגרור קבצים לכאן כדי להתחיל בהעלאה
|
||||
uploadPageSizeMessage = להשגת ביצועים מיטביים, מוטב לשמור על הקובץ מתחת לגודל של 1 ג״ב
|
||||
uploadPageBrowseButton1 = נא לבחור קובץ להעלאה
|
||||
uploadPageMultipleFilesAlert = העלאה של מספר קבצים או ספריה אינה נתמכת כרגע.
|
||||
uploadPageBrowseButtonTitle = העלאת קובץ
|
||||
uploadingPageProgress = { $filename } ({ $size }) בהעלאה
|
||||
importingFile = מתבצע ייבוא...
|
||||
verifyingFile = מתבצע אימות…
|
||||
importingFile = מתבצע ייבוא…
|
||||
encryptingFile = מתבצעת הצפנה...
|
||||
decryptingFile = מתבצע פענוח...
|
||||
notifyUploadDone = ההעלאה שלך הסתיימה
|
||||
uploadingPageMessage = אחרי שהקובץ שלך יעלה, ניתן יהיה להגדיר אפשרויות תפוגה.
|
||||
uploadCancelNotification = ההעלאה שלך בוטלה.
|
||||
uploadingPageLargeFileMessage = קובץ זה גדול ועלול לקחת זמן להעלות אותו. סבלנות!
|
||||
uploadingFileNotification = נא להודיע לי כשתסתיים ההעלאה.
|
||||
uploadSuccessConfirmHeader = מוכן לשליחה
|
||||
uploadSvgAlt = העלאה
|
||||
uploadSuccessTimingHeader = הקישור לקובץ שלך יפוג אחרי הורדה אחת או בעוד 24 שעות.
|
||||
copyUrlFormLabelWithName = ניתן להעתיק ולשתף את הקישור כדי לשלוח את הקובץ שלך: { $filename }
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] הורדה אחת
|
||||
*[other] { $num } הורדות
|
||||
}
|
||||
timespanHours =
|
||||
{ $num ->
|
||||
[one] שעה אחת
|
||||
[two] שעתיים
|
||||
*[other] { $num } שעות
|
||||
}
|
||||
copiedUrl = הועתק!
|
||||
deleteFileButton = מחיקת קובץ
|
||||
sendAnotherFileLink = שליחת קובץ נוסף
|
||||
# Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = הורדה
|
||||
# Used as header in a column indicating the number of times a file has been
|
||||
# downloaded
|
||||
downloadFileName = ההורדה נכשלה
|
||||
downloadFileSize = ({ $size })
|
||||
# Text and title used on the download link/button (indicates an action).
|
||||
unlockInputPlaceholder = ססמה
|
||||
unlockButtonLabel = שחרור נעילה
|
||||
downloadButtonLabel = הורדה
|
||||
downloadNotification = ההורדה הושלמה.
|
||||
downloadFinish = ההורדה הושלמה
|
||||
# This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } מתוך { $totalSize })
|
||||
downloadingPageProgress = בהורדה: { $filename } ({ $size })
|
||||
errorAltText = תקלה בהעלאה
|
||||
sendYourFilesLink = נסו את Firefox Send
|
||||
errorPageHeader = משהו השתבש!
|
||||
errorPageLink = שליחת קובץ נוסף
|
||||
fileTooBig = הקובץ הזה גדול מידי להעלאה. עליו להיות קטן מ־{ $size }.
|
||||
linkExpiredAlt = הקישור פג
|
||||
notSupportedHeader = הדפדפן שלך לא נתמך.
|
||||
notSupportedLink = למה אין תמיכה בדפדפן שלי?
|
||||
downloadFirefoxButtonSub = הורדה בחינם
|
||||
uploadedFile = קובץ
|
||||
copyFileList = העתקת כתובת
|
||||
# expiryFileList is used as a column header
|
||||
expiryFileList = יפוג בעוד
|
||||
deleteFileList = מחיקה
|
||||
nevermindButton = לא משנה
|
||||
legalHeader = תנאי שירות ופרטיות
|
||||
deletePopupText = למחוק דף זה?
|
||||
deletePopupYes = כן
|
||||
notSupportedOutdatedDetail = לצערנו גרסת Firefox זו לא תומכת בטכנולוגית הרשת שמפעילה את Firefox Send. יש לעדכן את הגרסה של הדפדפן שלך.
|
||||
updateFirefox = עדכון Firefox
|
||||
deletePopupCancel = ביטול
|
||||
deleteButtonHover = מחיקה
|
||||
copyUrlHover = העתקת קישור
|
||||
footerLinkLegal = מידע משפטי
|
||||
footerLinkPrivacy = פרטיות
|
||||
footerLinkTerms = תנאי שימוש
|
||||
footerLinkCookies = קובצי עוגיות
|
||||
passwordTryAgain = סיסמה שגויה. נא לנסות שוב.
|
||||
javascriptRequired = ל־Firefox Send דרוש JavaScript
|
||||
whyJavascript = למה ל־Firefox Send דרוש JavaScript?
|
||||
enableJavascript = נא להפעיל JavaScript ולנסות שוב.
|
||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||
expiresHoursMinutes = { $hours } שע׳ { $minutes } דק׳
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes } דק׳
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = אורך הססמה המרבי: { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = לא ניתן להגדיר את הססמה הזאת
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = Send
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = שיתוף קבצים פרטי ופשוט
|
||||
introDescription = { -send-brand } מאפשר לך לשתף קבצים עם הצפנה מקצה לקצה וקישור עם תפוגה אוטומטית. בצורה זו תוכלו לשתף קבצים באופן פרטי ולהבטיח שהדברים שלכם לא נשארים ברשת לנצח.
|
||||
notifyUploadEncryptDone = הקובץ שלך מוצפן ומוכן לשליחה
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = יפוג לאחר { $downloadCount } או { $timespan }
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] דקה אחת
|
||||
*[other] { $num } דקות
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] יום אחד
|
||||
[two] יומיים
|
||||
*[other] { $num } ימים
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] שבוע אחד
|
||||
[two] שבועיים
|
||||
*[other] { $num } שבועות
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] קובץ אחד
|
||||
*[other] { $num } קבצים
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = בתים
|
||||
# kibibyte abbreviation
|
||||
kb = ק״ב
|
||||
# mebibyte abbreviation
|
||||
mb = מ״ב
|
||||
# gibibyte abbreviation
|
||||
gb = ג״ב
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num } { $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = גודל כולל: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = יש להעתיק את הקישור כדי לשתף את הקובץ שלך:
|
||||
copyLinkButton = העתקת קישור
|
||||
downloadTitle = הורדת קבצים
|
||||
downloadDescription = קובץ זה שותף באמצעות { -send-brand } עם הצפנה מקצה לקצה וקישור שפג באופן אוטומטי.
|
||||
trySendDescription = כדאי לנסות את { -send-brand } לשיתוף קבצים פשוט ומאובטח.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] ניתן להעלות רק קובץ אחד בכל פעם.
|
||||
*[other] ניתן להעלות רק { $count } קבצים בכל פעם.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] רק ארכיון אחד מורשה.
|
||||
*[other] רק { $count } ארכיונים מורשים.
|
||||
}
|
||||
expiredTitle = פג תוקפו של קישור זה.
|
||||
notSupportedDescription = { -send-brand } לא יפעל עם דפדפן זה. { -send-short-brand } פועל בצורה הטובה ביותר עם הגרסה העדכנית ביותר של { -firefox }, ויעבוד עם הגרסה הנוכחית של רוב הדפדפנים.
|
||||
downloadFirefox = הורדת { -firefox }
|
||||
legalTitle = הצהרת פרטיות של { -send-short-brand }
|
||||
legalDateStamp = גרסה 1.0, בתאריך 12 במרץ 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days } ימים { $hours } שעות { $minutes } דקות
|
||||
addFilesButton = בחירת קבצים להעלאה
|
||||
uploadButton = העלאה
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = גרירה והשלכת קבצים
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = או ללחוץ כדי לשלוח קבצים עד לגודל של { $size }
|
||||
addPassword = הגנה באמצעות ססמה
|
||||
emailPlaceholder = נא להכניס כתובת דוא״ל
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = נא להירשם כדי לשלוח קבצים עד גודל של { $size }
|
||||
signInOnlyButton = כניסה
|
||||
accountBenefitTitle = נא ליצור חשבון { -firefox } או להיכנס לחשבון
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = שיתוף קבצים עד גודל של { $size }
|
||||
accountBenefitDownloadCount = שיתוף קבצים עם יותר אנשים
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] שמירה על קישורים פעילים עד ליום אחד
|
||||
*[other] שמירה על קישורים פעילים עד ל־{ $count } ימים
|
||||
}
|
||||
accountBenefitSync = ניהול קבצים משותפים מכל מכשיר
|
||||
accountBenefitMoz = מידע נוסף על שירותי { -mozilla } אחרים
|
||||
signOut = יציאה
|
||||
okButton = אישור
|
||||
downloadingTitle = בהורדה
|
||||
noStreamsWarning = ייתכן שדפדפן זה לא יוכל לפענח קובץ בגודל כזה.
|
||||
noStreamsOptionCopy = העתקת הקישור לפתיחה בדפדפן אחר
|
||||
noStreamsOptionFirefox = נסו את הדפדפן המועדף עלינו
|
||||
noStreamsOptionDownload = המשך בדפדפן זה
|
||||
downloadFirefoxPromo = { -send-short-brand } מובא אליך בחסות { -firefox }
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = שיתוף הקישור לקובץ שלך:
|
||||
shareLinkButton = שיתוף קישור
|
||||
# $name is the name of the file
|
||||
shareMessage = הורדת ״{ $name }״ עם { -send-brand }: שיתוף קבצים פשוט ובטוח
|
||||
trailheadPromo = ישנן דרכים נוספות להגן על הפרטיות שלכם. הצטרפו אל Firefox.
|
||||
learnMore = מידע נוסף.
|
||||
|
||||
@@ -160,3 +160,5 @@ shareLinkDescription = Dijelite poveznicu na svoju datoteku:
|
||||
shareLinkButton = Dijeli poveznicu
|
||||
# $name is the name of the file
|
||||
shareMessage = Preuzmite “{ $name }” sa { -send-brand }: jednostavno i sigurno dijeljenje datoteka
|
||||
trailheadPromo = Postoji način da zaštitite svoju privatnost. Pridružite se Firefoxu.
|
||||
learnMore = Saznajte više.
|
||||
|
||||
@@ -123,7 +123,7 @@ dragAndDropFiles = Traher e deponer files
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = o cliccar pro inviar usque { $size }
|
||||
addPassword = Proteger per contrasigno
|
||||
emailPlaceholder = Insere tu adresse email
|
||||
emailPlaceholder = Insere tu adresse de e-mail
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Accede pro inviar usque { $size }
|
||||
signInOnlyButton = Authentica te
|
||||
|
||||
@@ -142,3 +142,5 @@ shareLinkDescription = Bagikan tautan ke berkas Anda:
|
||||
shareLinkButton = Bagikan tautan
|
||||
# $name is the name of the file
|
||||
shareMessage = Unduh "{ $name }" dengan { -send-brand }: berbagi berkas dengan sederhana dan aman
|
||||
trailheadPromo = Ada cara untuk melindungi privasi Anda. Bergabunglah dengan Firefox.
|
||||
learnMore = Pelajari lebih lanjut.
|
||||
|
||||
@@ -140,3 +140,5 @@ shareLinkDescription = ファイルへのリンクを共有しましょう:
|
||||
shareLinkButton = リンクを共有
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand } で "{ $name }" をダウンロード: シンプルで安全なファイル共有
|
||||
trailheadPromo = プライバシーを保護する方法があります。Firefox を試してください。
|
||||
learnMore = 詳細情報
|
||||
|
||||
@@ -54,6 +54,10 @@ passwordSetError = Awal-agi uffir ur izmir ara ad ittwabaded
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Afessas, beṭṭu n ifuyla s wudem uslig
|
||||
introDescription = { -send-brand } ad k(yeǧǧ ad tebḍuḍ ifuyla iwgelhanensi ṭṭerf ɣer ṭṭerf akked useɣwen ara yemmten s wudem awurman. Daɣen, ad tizmireḍ ad tḥ€rzeḍ ayen i tbeṭṭuḍ s wudem uslig daɣen ad temneḍ imi agbur-ik ur yettɣimi ara srid i lebda.
|
||||
notifyUploadEncryptDone = Afaylu-ik yewgelhen daɣen ihegga i tuzna
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Ad yemmet deffir { $downloadCount } neɣ { $timespan }
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] 1 n tsedat
|
||||
@@ -90,18 +94,62 @@ totalSize = Tuɣzi s umata: { $size }
|
||||
copyLinkDescription = Nɣel aseɣwen akken ad tebḍuḍ afaylu-inek
|
||||
copyLinkButton = Nɣel aseɣwen
|
||||
downloadTitle = Sider ifuyla
|
||||
downloadDescription = Afaylu-a yettwabḍa s { -send-brand } s uwgelhen s ṭṭerf ɣer ṭṭerf s useɣwen ara yemmten s wudem awurman.
|
||||
trySendDescription = Ɛreḍ { -send-brand } i beḍḍu afessas n ifuyla s wudem ameɣtu.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Ala 1 n ufaylu i yemzren ad yali i tikkelt.
|
||||
*[other] Ala { $count } n yifuyla i yemzren ad alin i tikkelt.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Ala 1 n teṛcibt i yettwasirgen.
|
||||
*[other] Ala { $count } n teṛcibin i yettwasiregn.
|
||||
}
|
||||
expiredTitle = Immut useɣwen.
|
||||
notSupportedDescription = { -send-brand } ur iteddu ara s yiminig-a. { -send-short-brand } iteddu akken iwata s lqem aneggaru n { -firefox }, daɣen iteddu s lqem amiran n tuget n yiminigen.
|
||||
downloadFirefox = Sider { -firefox }
|
||||
legalTitle = Tasertit tabaḍnit n { -send-short-brand }
|
||||
legalDateStamp = Lqem 1.0, azemz n 12 Meɣres 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days } ass { $hours } srg { $minutes } tsd
|
||||
addFilesButton = Fren ifuyla ad tessaliḍ
|
||||
uploadButton = Sali
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = Ẓuɣer sakin sers ifuyla
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = neɣ sit akken ad tazneḍ arma d { $size }
|
||||
addPassword = Ḥrez s wawal uffir
|
||||
emailPlaceholder = Sekcem imayl inek
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Qqen akken ad tazneḍ arma d { $size }
|
||||
signInOnlyButton = Qqen
|
||||
accountBenefitTitle = Rnu amiḍan { -firefox } akken ad teqqneḍ
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Bḍu ifuyla arma d { $size }
|
||||
accountBenefitDownloadCount = Bḍu ifuyla d wugan n medden
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Eǧǧ iseɣwan d urmiden arma d 1 n wass
|
||||
*[other] Eǧǧ iseɣwan d urmiden arma d { $count } n wassan
|
||||
}
|
||||
accountBenefitSync = Sefrek ifuyla yebdan seg yal ibenk
|
||||
accountBenefitMoz = Issin ugar ɣef yimeẓla-nniḍen n { -mozilla }
|
||||
signOut = Ffeɣ
|
||||
okButton = IH
|
||||
downloadingTitle = Azdam
|
||||
noStreamsWarning = Iminig-a ur yezmir ara ad yezmek afaylu meqqren.
|
||||
noStreamsOptionCopy = Nɣel aseɣwen i tulya deg yiminig-nniden
|
||||
noStreamsOptionFirefox = Ɛreḍ iminig-ik ufrin
|
||||
noStreamsOptionDownload = Kemmel akked iminig-a
|
||||
downloadFirefoxPromo = { -send-short-brand } yettwasumer i yal { -firefox } amaynut.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Bḍu aseɣwen ɣer ufaylu-ik:
|
||||
shareLinkButton = Bḍu aseɣwen
|
||||
# $name is the name of the file
|
||||
shareMessage = Sider "{ $name }" s { -send-brand }: d fessas, d aɣelsan i beṭṭu n yifuyla.
|
||||
trailheadPromo = Yella wallal n ummesten n tudert-ik tusligt. Ddu ɣer Firefox.
|
||||
learnMore = Issin ugar.
|
||||
|
||||
@@ -4,8 +4,8 @@ siteFeedback = 사용자 의견
|
||||
importingFile = 가져오는 중…
|
||||
encryptingFile = 암호화 중…
|
||||
decryptingFile = 복호화 중…
|
||||
downloadCount = { $num } 다운로드
|
||||
timespanHours = 1 시간
|
||||
downloadCount = 다운로드 { $num }회
|
||||
timespanHours = { $num }시간
|
||||
copiedUrl = 복사 완료!
|
||||
unlockInputPlaceholder = 비밀번호
|
||||
unlockButtonLabel = 잠금 해제
|
||||
@@ -49,7 +49,7 @@ introTitle = 간단하고, 사생활을 보호하는 파일 공유
|
||||
introDescription = { -send-brand }를 사용하면 종단 암호화와 자동으로 만료되는 링크를 사용해 파일을 공유할 수 있습니다. 안전하게 공유할 수 있고 공유된 파일이 계속 온라인에 남지 않게 됩니다.
|
||||
notifyUploadEncryptDone = 파일이 암호화 되어서 보낼 수 있게 됐습니다
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = { $downloadCount }나 { $timespan } 후 만료됨
|
||||
archiveExpiryInfo = { $downloadCount } 혹은 { $timespan } 후 만료됨
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
*[other] { $num }분
|
||||
@@ -112,7 +112,7 @@ addPassword = 비밀번호로 파일 보호
|
||||
emailPlaceholder = 이메일 입력
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = { $size }까지 파일을 보낼 수 있게 로그인
|
||||
signInButton = 로그인/등록
|
||||
signInOnlyButton = 로그인
|
||||
accountBenefitTitle = { -firefox } 계정을 하나 만들거나, 로그인
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = { $size }까지의 파일 공유
|
||||
@@ -130,3 +130,11 @@ noStreamsWarning = 이 브라우저는 이렇게 큰 용량의 파일 암호화
|
||||
noStreamsOptionCopy = 다른 브라우저에서 열 수 있도록 링크를 복사
|
||||
noStreamsOptionFirefox = 우리가 애용하는 브라우저를 사용해 보세요
|
||||
noStreamsOptionDownload = 이 브라우저로 계속하기
|
||||
downloadFirefoxPromo = 완전히 새로운 { -firefox }로 { -send-short-brand }가 제공됩니다.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = 파일 링크 공유:
|
||||
shareLinkButton = 링크 공유
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand }으로 “{ $name }” 파일을 내려받으세요: 쉽고 안전한 파일 공유입니다.
|
||||
trailheadPromo = 개인 정보를 보호하는 방법이 있습니다. 파이어폭스와 함께 하세요.
|
||||
learnMore = 자세히 알아보기
|
||||
|
||||
@@ -168,3 +168,5 @@ shareLinkDescription = Pasidalinkite saitu į jūsų failą:
|
||||
shareLinkButton = Dalintis saitu
|
||||
# $name is the name of the file
|
||||
shareMessage = Atsisiųskite „{ $name }“ su „{ -send-brand }“: paprastas, saugus dalinimasis failais
|
||||
trailheadPromo = Yra būdas apsaugoti jūsų privatumą. Naudokite „Firefox“.
|
||||
learnMore = Sužinoti daugiau.
|
||||
|
||||
@@ -54,6 +54,7 @@ passwordSetError = Dette passordet kunne ikke settes
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Enkel, privat fildeling
|
||||
introDescription = { -send-brand } lar deg dele filer via en tidsbegrenset lenke med ende-til-ende-kryptering. På den måten kan du dele filer privat og samtidig være trygg på at filene dine ikke blir liggende på nettet for alltid.
|
||||
notifyUploadEncryptDone = Filen din er kryptert og klar til å sende
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Utløper etter { $downloadCount } eller { $timespan }
|
||||
@@ -77,9 +78,78 @@ fileCount =
|
||||
[one] 1 fil
|
||||
*[other] { $num } filer
|
||||
}
|
||||
# size is a localized number followed by a unit of bytes, ex. 2.5GB
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
kb = KB
|
||||
# mebibyte abbreviation
|
||||
mb = MB
|
||||
# gibibyte abbreviation
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Total størrelse: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Kopier lenken for å dele filen din:
|
||||
copyLinkButton = Kopier lenke
|
||||
downloadTitle = Last ned filer
|
||||
downloadDescription = Denne filen ble delt via { -send-brand } med ende-til-ende-kryptering og en lenke som automatisk utløper.
|
||||
trySendDescription = Prøv { -send-brand } for enkel, sikker fildeling.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Kun 1 fil kan lastes opp om gangen.
|
||||
*[other] Kun { $count } filer kan lastes opp om gangen.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Kun 1 arkiv er tillatt.
|
||||
*[other] Kun { $count } arkiver er tillatt.
|
||||
}
|
||||
expiredTitle = Denne lenken er utløpt.
|
||||
notSupportedDescription = { -send-brand } virker ikke med denne nettleseren. { -send-short-brand } fungerer best med den nyeste versjonen av { -firefox }, og vil fungere med den nyeste versjonen av de fleste nettlesere.
|
||||
downloadFirefox = Last ned { -firefox }
|
||||
legalTitle = { -send-short-brand } Personvernerklæring
|
||||
legalDateStamp = Versjon 1.0, datert den 12. mars 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }d { $hours }t { $minutes }m
|
||||
addFilesButton = Velg filer du vil laste opp
|
||||
uploadButton = Last opp
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = Dra og slipp filer
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = eller klikk for å sende filer på opptil { $size }
|
||||
addPassword = Beskytt med passord
|
||||
emailPlaceholder = Skriv inn e-postadressen din
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Logg inn for å sende opptil { $size }
|
||||
signInOnlyButton = Logg inn
|
||||
accountBenefitTitle = Opprett en { -firefox }-konto eller logg inn
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Del filer på opptil { $size }
|
||||
accountBenefitDownloadCount = Del filer med flere personer
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Hold lenker aktiv opptil 1 dag
|
||||
*[other] Hold lenker aktiv opptil { $count } dager
|
||||
}
|
||||
accountBenefitSync = Behandle delte filer fra en hvilken som helst enhet
|
||||
accountBenefitMoz = Les om andre { -mozilla }-tjenester
|
||||
signOut = Logg ut
|
||||
okButton = OK
|
||||
downloadingTitle = Laster ned
|
||||
noStreamsWarning = Denne nettleseren kan kanskje ikke dekryptere en så stor fil.
|
||||
noStreamsOptionCopy = Kopier lenken for å åpne den i en annen nettleser
|
||||
noStreamsOptionFirefox = Prøv favorittnettleseren vår
|
||||
noStreamsOptionDownload = Fortsett med denne nettleseren
|
||||
downloadFirefoxPromo = { -send-short-brand } presenteres for deg av den helt nye { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Del lenken til filen din:
|
||||
shareLinkButton = Del lenke
|
||||
# $name is the name of the file
|
||||
shareMessage = Last ned ‹{ $name }› med { -send-brand }: enkel, trygg fildeling
|
||||
trailheadPromo = Det finnes en måte å ta vare på personvernet ditt. Bruk Firefox.
|
||||
learnMore = Les mer.
|
||||
|
||||
155
public/locales/oc/send.ftl
Normal file
155
public/locales/oc/send.ftl
Normal file
@@ -0,0 +1,155 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteFeedback = Comentaris
|
||||
importingFile = Importacion…
|
||||
encryptingFile = Chiframent…
|
||||
decryptingFile = Deschiframent…
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] 1 telecargament
|
||||
*[other] { $num } telecargaments
|
||||
}
|
||||
timespanHours =
|
||||
{ $num ->
|
||||
[one] 1 ora
|
||||
*[other] { $num } oras
|
||||
}
|
||||
copiedUrl = Copiat !
|
||||
unlockInputPlaceholder = Senhal
|
||||
unlockButtonLabel = Desverrolhar
|
||||
downloadButtonLabel = Telecargar
|
||||
downloadFinish = Telecargament acabat
|
||||
fileSizeProgress = ({ $partialSize } sus { $totalSize })
|
||||
sendYourFilesLink = Ensajar Firefox Send
|
||||
errorPageHeader = I a quicòm que truca.
|
||||
fileTooBig = Aqueste fichièr es tròp gròs per l’enviar. Sa talha deu èsser inferiora a { $size }.
|
||||
linkExpiredAlt = Lo ligam a expirat
|
||||
notSupportedHeader = Vòstre navegador es pas compatible.
|
||||
notSupportedLink = Perqué mon navegador es pas compatible ?
|
||||
notSupportedOutdatedDetail = Aquesta version de Firefox es pas compatibla amb la tecnologia web amb la quala fonciona Firefox Send. Vos cal metre a jorn lo navegador.
|
||||
updateFirefox = Metre a jorn Firefox
|
||||
deletePopupCancel = Anullar
|
||||
deleteButtonHover = Suprimir
|
||||
footerLinkLegal = Mencions legalas
|
||||
footerLinkPrivacy = Vida privada
|
||||
footerLinkCookies = Cookies
|
||||
passwordTryAgain = Senhal incorrècte. Tornatz ensajar.
|
||||
javascriptRequired = Firefox Send requesís JavaScript
|
||||
whyJavascript = Perque Firefox Send requesís JavaScript ?
|
||||
enableJavascript = Volgatz activar lo JavaScript e ensajatz tornamai.
|
||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||
expiresHoursMinutes = { $hours } h { $minutes } min
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes } min
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = Talha maximala del senhal : { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = Aqueste senhal a pas pogut èsser definit
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = Send
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Partatge simple e privat de fichièrs
|
||||
introDescription = { -send-brand } vos permet de partejar de fichièr amb un chiframent del cap a la fin e un ligam qu’expira automaticament. Atal podètz gardar privat çò que partejatz e vos assegurar que demorarà pas en linha per totjorn.
|
||||
notifyUploadEncryptDone = Vòstre fichièr es chifrat e prèst per mandadís
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Expira aprèp { $downloadCount } o { $timespan }
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] 1 minuta
|
||||
*[other] { $num } minutas
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] 1 jorn
|
||||
*[other] { $num } jorns
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] 1 setmana
|
||||
*[other] { $num } setmanas
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] 1 fichièr
|
||||
*[other] { $num } fichièrs
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = o
|
||||
# kibibyte abbreviation
|
||||
kb = Ko
|
||||
# mebibyte abbreviation
|
||||
mb = Mo
|
||||
# gibibyte abbreviation
|
||||
gb = Go
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num } { $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Talha totala : { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Copiatz lo ligam per partejar vòstre fichièr :
|
||||
copyLinkButton = Copiar lo ligam
|
||||
downloadTitle = Telecargar los fichièrs
|
||||
downloadDescription = Aqueste fichièr foguèt partejat via { -send-brand } amb chiframent del cap a la fin e un ligam qu’expira automaticament.
|
||||
trySendDescription = Ensajatz { -send-brand } per un partiment de fichièrs simple e segur.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Òm pòt pas qu’enviar 1 fichièr al còp.
|
||||
*[other] Òm pòt pas qu’enviar { $count } fichièrs al còp.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Pas qu’un archiu es autorizat.
|
||||
*[other] Pas que { $count } archius son autorizats.
|
||||
}
|
||||
expiredTitle = Aqueste ligam a expirat.
|
||||
notSupportedDescription = { -send-brand } foncionarà pas amb aqueste navegador. { -send-short-brand } fonciona melhor amb la darrièra version de { -firefox } e foncionarà amb la version mai recenta de la màger part dels navegadors.
|
||||
downloadFirefox = Telecargar { -firefox }
|
||||
legalTitle = Avís de confidencialitat de { -send-short-brand }
|
||||
legalDateStamp = Version 1.0 del 12 de març de 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days } j { $hours } h { $minutes } min
|
||||
addFilesButton = Seleccionatz los fichièrs de mandar
|
||||
uploadButton = Enviar
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = Lissatz-depausatz de fichièrs
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = o clicatz per enviar fins a { $size }
|
||||
addPassword = Protegir amb un senhal
|
||||
emailPlaceholder = Picatz vòstra adreça electronica
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Connectatz-vos per enviar fins a { $size }
|
||||
signInOnlyButton = Connexion
|
||||
accountBenefitTitle = Creatz un compte { -firefox } o connectatz-vos
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Partejatz de fichièrs fins a { $size }
|
||||
accountBenefitDownloadCount = Partejatz de fichièrs amb mai de personas
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Mantenètz los ligams actius fins a 1 jorn
|
||||
*[other] Mantenètz los ligams actius fins a { $count } jorns
|
||||
}
|
||||
accountBenefitSync = Gerissètz los fichièrs partejats de qualque siá periferic estant
|
||||
accountBenefitMoz = Aprenètz-ne mai suls autres servicis { -mozilla }
|
||||
signOut = Desconnexion
|
||||
okButton = D'acòrd
|
||||
downloadingTitle = Telecargament
|
||||
noStreamsWarning = Pòt arribar qu’aqueste navegador pòsca pas deschifrar un fichièr tan gròs.
|
||||
noStreamsOptionCopy = Copiatz lo ligam per lo dobrir dins un autre navegador
|
||||
noStreamsOptionFirefox = Ensajatz nòstre navegador preferit
|
||||
noStreamsOptionDownload = Contunhar amb aqueste navegador
|
||||
downloadFirefoxPromo = Lo nòu { -firefox } vos provesís { -send-short-brand }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Partejatz lo ligam cap a vòstre fichièr :
|
||||
shareLinkButton = Partejar lo ligam
|
||||
# $name is the name of the file
|
||||
shareMessage = Telecargar « { $name } » amb { -send-brand } : un biais simple e segur de partejar de fichièrs.
|
||||
trailheadPromo = Existís un biais de protegir vòstra vida privada. Rejonhètz Firefox.
|
||||
learnMore = Ne saber mai.
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = ਆਪਣੀ ਫਾਇਲ ਲਈ ਲਿੰਕ ਸਾਂ
|
||||
shareLinkButton = ਲਿੰਕ ਸਾਂਝਾ ਕਰੋ
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand } ਨਾਲ "{ $name }" ਡਾਊਨਲੋਡ ਕਰੋ: ਸੌਖਾ, ਸੁਰੱਖਿਅਤ ਫਾਇਲ ਸਾਂਝਾ ਕਰਨਾ
|
||||
trailheadPromo = ਤੁਹਾਡੀ ਪਰਦੇਦਾਰੀ ਦੀ ਸੁਰੱਖਿਆ ਦਾ ਢੰਗ ਹੈ। ਫਾਇਰਫਾਕਸ ਨਾਲ ਜੁੜੋ।
|
||||
learnMore = ਹੋਰ ਸਿੱਖੋ
|
||||
|
||||
@@ -54,7 +54,7 @@ passwordSetError = Essa senha não pôde ser definida
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Compartilhamento de arquivos fácil e privativo
|
||||
introDescription = O { -send-brand } permite compartilhar arquivos com criptografia ponto a ponto e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre.
|
||||
introDescription = O { -send-brand } permite compartilhar arquivos com criptografia de ponta a ponta e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre.
|
||||
notifyUploadEncryptDone = Seu arquivo foi criptografado e está pronto para ser enviado
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Expirar após { $downloadCount } ou { $timespan }
|
||||
@@ -94,7 +94,7 @@ totalSize = Tamanho total: { $size }
|
||||
copyLinkDescription = Copie o link para compartilhar seu arquivo:
|
||||
copyLinkButton = Copiar link
|
||||
downloadTitle = Baixar arquivos
|
||||
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia ponto a ponto e um link que expira automaticamente.
|
||||
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia de ponta a ponta e um link que expira automaticamente.
|
||||
trySendDescription = Experimente o { -send-brand } para compartilhamento de arquivos simples e seguro.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
@@ -127,23 +127,23 @@ emailPlaceholder = Informe seu e-mail
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Entre na sua conta para enviar até { $size }
|
||||
signInOnlyButton = Entrar
|
||||
accountBenefitTitle = Crie uma Conta { -firefox } ou entre na sua conta
|
||||
accountBenefitTitle = Crie uma Conta { -firefox } ou entre se já tiver
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Compartilhe arquivos até { $size }
|
||||
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas
|
||||
accountBenefitLargeFiles = Compartilhe arquivos até { $size }.
|
||||
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas.
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Mantenha links ativos por até 1 dia
|
||||
*[other] Mantenha links ativos por até { $count } dias
|
||||
[one] Mantenha links ativos por até 1 dia.
|
||||
*[other] Mantenha links ativos por até { $count } dias.
|
||||
}
|
||||
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo
|
||||
accountBenefitMoz = Conheça outros serviços da { -mozilla }
|
||||
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo.
|
||||
accountBenefitMoz = Conheça outros serviços da { -mozilla }.
|
||||
signOut = Sair
|
||||
okButton = OK
|
||||
downloadingTitle = Baixando
|
||||
noStreamsWarning = Este navegador pode não conseguir descriptografar um arquivo tão grande.
|
||||
noStreamsOptionCopy = Copiar o link para abrir em outro navegador
|
||||
noStreamsOptionFirefox = Experimentar nosso navegador preferido
|
||||
noStreamsOptionFirefox = Experimente nosso navegador preferido
|
||||
noStreamsOptionDownload = Continuar com este navegador
|
||||
downloadFirefoxPromo = O { -send-short-brand } é apresentado pelo novo { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
@@ -151,5 +151,5 @@ shareLinkDescription = Compartilhe o link para o seu arquivo:
|
||||
shareLinkButton = Compartilhar link
|
||||
# $name is the name of the file
|
||||
shareMessage = Baixe "{ $name }" com o { -send-brand }: compartilhamento de arquivos simples e seguro
|
||||
trailheadPromo = Existe um meio de proteger sua privacidade. Cadastre-se no Firefox.
|
||||
trailheadPromo = Existe um meio de proteger sua privacidade. Use o Firefox.
|
||||
learnMore = Saiba mais.
|
||||
|
||||
@@ -23,7 +23,7 @@ downloadButtonLabel = Descarcă
|
||||
downloadFinish = Descărcare încheiată
|
||||
fileSizeProgress = ({ $partialSize } din { $totalSize })
|
||||
sendYourFilesLink = Încearcă Firefox Send
|
||||
errorPageHeader = Ceva a mers prost!
|
||||
errorPageHeader = Ceva nu a funcționat!
|
||||
fileTooBig = Acest fișier este prea mare. Ar trebuie să fie sub { $size }.
|
||||
linkExpiredAlt = Link expirat
|
||||
notSupportedHeader = Browserul tău nu este suportat.
|
||||
@@ -35,7 +35,7 @@ deleteButtonHover = Șterge
|
||||
footerLinkLegal = Mențiuni legale
|
||||
footerLinkPrivacy = Confidențialitate
|
||||
footerLinkCookies = Cookie-uri
|
||||
passwordTryAgain = Parola este incorectă. Încearcă din nou.
|
||||
passwordTryAgain = Parolă incorectă. Încearcă din nou.
|
||||
javascriptRequired = Firefox Send necesită JavaScript
|
||||
whyJavascript = De ce Firefox Send necesită JavaScript?
|
||||
enableJavascript = Te rugăm să reactivezi JavaScript și să încerci din nou.
|
||||
@@ -56,7 +56,7 @@ passwordSetError = Această parolă nu a putut fi setată
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Partajare de fișiere simplă și privată
|
||||
introDescription = { -send-brand } îți permite să partajezi fișiere cu criptare end-to-end și un link care expiră automat. Deci, poți păstra confidențial ceea ce partajezi și te poți asigura că ce ai partajat nu rămâne online pentru totdeauna.
|
||||
introDescription = { -send-brand } îți permite să partajezi fișiere cu criptare capăt-la-capăt și un link care expiră automat. Deci, poți păstra confidențial ceea ce partajezi și te poți asigura că ce ai partajat nu rămâne online pentru totdeauna.
|
||||
notifyUploadEncryptDone = Fișierul tău este criptat și gata de trimitere
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Expiră după { $downloadCount } sau { $timespan }
|
||||
@@ -100,8 +100,8 @@ totalSize = Mărime totală: { $size }
|
||||
copyLinkDescription = Copiază linkul pentru partajarea fișierului:
|
||||
copyLinkButton = Copiază linkul
|
||||
downloadTitle = Descarcă fișierele
|
||||
downloadDescription = Acest fișier a fost partajat prin { -send-brand }, cu criptare end-to-end și un link ce expiră automat.
|
||||
trySendDescription = Încearcă { -send-brand } pentru o partajare de fișiere simplă și sigură.
|
||||
downloadDescription = Acest fișier a fost partajat prin { -send-brand }, cu criptare capăt-la-capăt și un link care expiră automat.
|
||||
trySendDescription = Încearcă { -send-brand } pentru o partajare simplă și sigură a fișierelor.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
@@ -133,7 +133,7 @@ orClickWithSize = sau dă clic pentru a trimite până la { $size }
|
||||
addPassword = Protejează cu parolă
|
||||
emailPlaceholder = Introdu e-mailul tău
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Autentifică-te ca să trimiți până la { $size }
|
||||
signInSizeBump = Autentifică-te pentru a trimite până la { $size }
|
||||
signInOnlyButton = Autentificare
|
||||
accountBenefitTitle = Creează un cont { -firefox } sau autentifică-te
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
@@ -160,5 +160,5 @@ shareLinkDescription = Partajează linkul către fișier:
|
||||
shareLinkButton = Partajează linkul
|
||||
# $name is the name of the file
|
||||
shareMessage = Descarcă „{ $name }” cu { -send-brand }: partajare simplă și sigură a fișierelor
|
||||
trailheadPromo = Există o modalitate de a-ți proteja confidențialitatea. Alătură-te Firefox.
|
||||
trailheadPromo = Există o modalitate de a-ți proteja viața privată. Alătură-te Firefox.
|
||||
learnMore = Află mai multe.
|
||||
|
||||
@@ -24,7 +24,7 @@ downloadFinish = Загрузка завершена
|
||||
fileSizeProgress = ({ $partialSize } из { $totalSize })
|
||||
sendYourFilesLink = Попробовать Firefox Send
|
||||
errorPageHeader = Что-то пошло не так!
|
||||
fileTooBig = Этот файл слишком большой для загрузки. Он должен быть меньше { $size }.
|
||||
fileTooBig = Файл слишком большой. Он должен быть меньше { $size }.
|
||||
linkExpiredAlt = Истёк срок действия ссылки
|
||||
notSupportedHeader = Ваш браузер не поддерживается.
|
||||
notSupportedLink = Почему мой браузер не поддерживается?
|
||||
@@ -160,3 +160,5 @@ shareLinkDescription = Поделитесь ссылкой на ваш файл:
|
||||
shareLinkButton = Поделиться ссылкой
|
||||
# $name is the name of the file
|
||||
shareMessage = Загрузите «{ $name }» с { -send-brand }: простой и безопасный обмен файлами
|
||||
trailheadPromo = Существует способ защитить вашу приватность. Присоединяйтесь к Firefox.
|
||||
learnMore = Подробнее.
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteFeedback = Zvirikutaurwa
|
||||
uploadPageLearnMore = Dzidza zvimwe
|
||||
# Used as header in a column indicating the amount of time left before a
|
||||
# download link expires (e.g. "10h 5m")
|
||||
timeFileList = Nguva
|
||||
deletePopupYes = Hongu
|
||||
changePasswordButton = Shandura
|
||||
importingFile = Kutora faira
|
||||
encryptingFile = Kuinikiriputa
|
||||
enableJavascript = Ndinokumbira mubvumidze JavaScript moedza zvekare
|
||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||
expiresHoursMinutes = { $hours }maawa { $minutes }mineti
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes }mineti
|
||||
# A short status message shown when a password is successfully set
|
||||
passwordIsSet = Pasiwedhi yaita
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = Pasiwedhi haipfuuri mavara:{ $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = Pasiwedhi haina kuita
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = Ndani me të tjerët lidhjen për te kartela juaj:
|
||||
shareLinkButton = Ndani me të tjerët lidhjen
|
||||
# $name is the name of the file
|
||||
shareMessage = Shkarkojeni “{ $name }” me { -send-brand }: shkëmbim kartelash dhe thjesht dhe pa rrezik
|
||||
trailheadPromo = Ka një rrugë për të mbrojtur privatësinë tuaj. Bëhuni pjesë e Firefox-it.
|
||||
learnMore = Mësoni më tepër.
|
||||
|
||||
@@ -134,7 +134,7 @@ addPassword = Заштитите лозинком
|
||||
emailPlaceholder = Унесите вашу е-адресу
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Пријавите се да пошаљете садржај до { $size }
|
||||
signInButton = Пријава/регистрација
|
||||
signInOnlyButton = Пријавите се
|
||||
accountBenefitTitle = Направите { -firefox } налог или се пријавите
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Поделите датотеке велике до { $size }
|
||||
@@ -154,3 +154,11 @@ noStreamsWarning = Овај прегледач можда неће моћи да
|
||||
noStreamsOptionCopy = Копирај везу за отварање у другом прегледачу
|
||||
noStreamsOptionFirefox = Пробајте наш омиљени прегледач
|
||||
noStreamsOptionDownload = Наставите у овом прегледачу
|
||||
downloadFirefoxPromo = { -send-short-brand } вам је омогућен захваљући потпуно новом програму { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Поделите везу до датотеке:
|
||||
shareLinkButton = Поделите везу
|
||||
# $name is the name of the file
|
||||
shareMessage = Преузмите „{ $name }“ помоћу програма { -send-brand }: једноставно и безбедно дељење датотека
|
||||
trailheadPromo = Постоји начин да заштитите вашу приватност. Придружите се Firefox-у.
|
||||
learnMore = Сазнајте више.
|
||||
|
||||
@@ -30,7 +30,7 @@ deletePopupCancel = Bolay
|
||||
deleteButtonHover = Pupus
|
||||
footerLinkLegal = Légal
|
||||
footerLinkPrivacy = Privasi
|
||||
footerLinkCookies = Kuki
|
||||
footerLinkCookies = Réréméh
|
||||
passwordTryAgain = Kecap sandi salah. Pecakan deui.
|
||||
javascriptRequired = Firefox Send merlukeun JavaScript
|
||||
whyJavascript = Naha Firefox Send merlukeun JavaScript?
|
||||
|
||||
@@ -1,29 +1,9 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = జాల ప్రయోగం
|
||||
siteFeedback = అభిప్రాయం
|
||||
uploadPageLearnMore = ఇంకా తెలుసుకోండి
|
||||
uploadPageDropMessage = ఎగుమతిని ప్రారంభించడానికి మీ ఫైలును ఇక్కడ విడిచిపెట్టండి
|
||||
uploadPageSizeMessage = అత్యంత నమ్మకమైన కార్యం కోసం, మీ ఫైలును 1GB కంటే తక్కువగా ఉంచడం ఉత్తమం
|
||||
uploadPageBrowseButton = మీ కంప్యూటర్లో ఒక ఫైలును ఎంచుకోండి
|
||||
uploadPageBrowseButton1 = ఎక్కించటానికి ఒక ఫైలును ఎంచుకోండి
|
||||
uploadPageMultipleFilesAlert = పలు ఫైళ్ళను లేదా సంయచాన్ని ఎక్కించడానికి ప్రస్తుతం తోడ్పాటు లేదు.
|
||||
uploadPageBrowseButtonTitle = ఫైలును ఎగుమతి చేయండి
|
||||
uploadingPageProgress = { $filename } ({ $size }) ఎక్కుతోంది
|
||||
importingFile = దిగుమతవుతోంది...
|
||||
verifyingFile = పరిశీలిస్తున్నది…
|
||||
encryptingFile = గుప్తీకరిస్తోంది...
|
||||
decryptingFile = వ్యక్తపరుస్తోంది...
|
||||
notifyUploadDone = మీ ఎగుమతి పూర్తయింది.
|
||||
uploadingPageMessage = మీ ఫైలును మీరు ఎగుమతి చేసిన తర్వాత గడువు ఎంపికలను సరిగా ఏర్పాటు చేయగలరు.
|
||||
uploadingPageCancel = ఎగుమతి రద్దు చేయండి
|
||||
uploadCancelNotification = మీ ఎగుమతి రద్దు చేయబడింది.
|
||||
uploadingPageLargeFileMessage = ఈ ఫైలు పెద్దగా ఉంది అందువలన ఎగుమతి చేయడానికి కొంత సమయం పట్టవచ్చు. వేచి ఉండండి!
|
||||
uploadingFileNotification = ఎగుమతి పూర్తయినప్పుడు నాకు తెలియచేయండి.
|
||||
uploadSuccessConfirmHeader = పంపించడానికి సిద్ధంగా ఉంది
|
||||
uploadSvgAlt = ఎగుమతి చేయండి
|
||||
uploadSuccessTimingHeader = మీ ఫైలు లంకె గడువు 1 దిగుమతి తరువాత లేదా 24 గంటల తరువాత ముగుస్తుంది.
|
||||
expireInfo = మీ ఫైలుకు లంకె { $downloadCount } లేదా { $timespan } తర్వాత గడువు అవుతుంది.
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] 1 దింపుకోలు
|
||||
@@ -34,68 +14,26 @@ timespanHours =
|
||||
[one] 1 గంట
|
||||
*[other] { $num } గంటలు
|
||||
}
|
||||
copyUrlFormLabelWithName = మీ ఫైల్ను పంపడానికి లంకెను నకలు చేయండి మరియు పంచండి: { $filename }
|
||||
copyUrlFormButton = క్లిప్బోర్డ్కు నకలు చేయండి
|
||||
copiedUrl = నకలు చేయబడింది!
|
||||
deleteFileButton = ఫైలును తొలగించండి
|
||||
sendAnotherFileLink = మరో ఫైలును పంపండి
|
||||
# Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = దిగుమతి
|
||||
downloadsFileList = దింపుకోళ్ళు
|
||||
# Used as header in a column indicating the amount of time left before a
|
||||
# download link expires (e.g. "10h 5m")
|
||||
timeFileList = సమయం
|
||||
# Used as header in a column indicating the number of times a file has been
|
||||
# downloaded
|
||||
downloadFileName = దిగుమతి { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = సంకేతపదాన్ని తెలపండి
|
||||
unlockInputPlaceholder = సంకేతపదం
|
||||
unlockButtonLabel = తాళం తీయి
|
||||
# Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = దిగుమతి
|
||||
downloadNotification = మీ దిగుమతి పూర్తయ్యింది.
|
||||
downloadFinish = దిగుమతి పూర్తయింది
|
||||
# This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = { $totalSize }) యొక్క ({ $partialSize }
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox sendను ప్రయత్నించండి
|
||||
downloadingPageProgress = దిగుమతిచేస్తున్నది { $filename } ({ $size })
|
||||
errorAltText = ఎగుమతిలో లోపం
|
||||
errorPageHeader = ఏదో తప్పిదం జరిగింది!
|
||||
errorPageMessage = ఫైల్ను ఎగుమతి చేయడంలో లోపం ఉంది.
|
||||
errorPageLink = మరో ఫైలును పంపండి
|
||||
fileTooBig = ఆ ఫైలు ఎక్కించడానికి చాలా పెద్దగా ఉంది. ఫైళ్ళు { $size } కంటే తక్కువ పరిమాణంలో ఉండాలి.
|
||||
linkExpiredAlt = లంకె గడువు ముగిసింది
|
||||
expiredPageHeader = ఈ లంకె గడువు ముగిసింది లేదా ముందు ఎప్పుడూ ఉనికిలో లేదు!
|
||||
notSupportedHeader = మీ విహారిణికి మద్దతు లేదు.
|
||||
notSupportedLink = నా విహారిణికి ఎందుకు మద్దతు లేదు?
|
||||
notSupportedOutdatedDetail = దురదృష్టవశాత్తు Firefox యొక్క ఈ వెర్షన్ Firefox సాంకేతికతను పంపే వెబ్ సాంకేతికతకు మద్దతు ఇవ్వదు. మీరు మీ బ్రౌజర్ని నవీకరించాలి.
|
||||
updateFirefox = Firefoxను నవీకరించు
|
||||
downloadFirefoxButtonSub = ఉచిత దిగుమతులు
|
||||
uploadedFile = దస్త్రం
|
||||
copyFileList = URL నకలుతీయి
|
||||
# expiryFileList is used as a column header
|
||||
expiryFileList = ఇంతలో గడువుతీరును
|
||||
deleteFileList = తొలగించు
|
||||
nevermindButton = పర్వాలేదు
|
||||
legalHeader = నిబంధనలు మరియు గోప్యత
|
||||
deletePopupText = ఈ ఫైలును తొలగించాలా?
|
||||
deletePopupYes = అవును
|
||||
deletePopupCancel = రద్దుచేయి
|
||||
deleteButtonHover = తొలగించు
|
||||
copyUrlHover = URLను నకలు చేయండి
|
||||
footerLinkLegal = చట్టపరమైన
|
||||
# Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = టెస్ట్ పైలట్ గురించి
|
||||
footerLinkPrivacy = గోప్యత
|
||||
footerLinkTerms = నియమాలు
|
||||
footerLinkCookies = కుకీలు
|
||||
requirePasswordCheckbox = ఈ ఫైల్ను దింపుకోటానికి సంకేతపదం అవసరం
|
||||
addPasswordButton = సంకేతపదం జోడించండి
|
||||
changePasswordButton = మార్చు
|
||||
passwordTryAgain = సరికాని సంకేతపదం. మళ్ళీ ప్రయత్నించండి.
|
||||
reportIPInfringement = మేధో సంపత్తి హక్కుల ఉల్లంఘనను నివేదించండి
|
||||
javascriptRequired = Firefox Sendకి జావాస్క్రిప్టు కావాలి
|
||||
whyJavascript = Firefox Sendకి జావాస్క్రిప్టు ఎందుకు కావాలి?
|
||||
enableJavascript = జావాస్క్రిప్టు చేతనంచేసి మళ్ళీ ప్రయత్నించండి.
|
||||
@@ -103,9 +41,86 @@ enableJavascript = జావాస్క్రిప్టు చేతనంచ
|
||||
expiresHoursMinutes = { $hours }గం { $minutes }ని
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes }ని
|
||||
# A short status message shown when a password is successfully set
|
||||
passwordIsSet = సంకేతపదం అమరింది
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = సంకేతపదం గరిష్ఠ పొడవు: { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = ఈ సంకేతపదం పెట్టలేకపోయాం
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = పంపించు
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] 1 నిమిషం
|
||||
*[other] { $num } నిమిషాలు
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] 1 రోజు
|
||||
*[other] { $num } రోజులు
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] 1 వారం
|
||||
*[other] { $num } వారాలు
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] 1 ఫైలు
|
||||
*[other] { $num } ఫైళ్లు
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
kb = KB
|
||||
# mebibyte abbreviation
|
||||
mb = MB
|
||||
# gibibyte abbreviation
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = మొత్తం పరిమాణం: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = మీ ఫైలును భాగస్వామ్యం చేయడానికి ఈ లంకెను నకలు చేయండి:
|
||||
copyLinkButton = లంకెను నకలుతీయి
|
||||
downloadTitle = ఫైళ్లను దింపుకోండి
|
||||
expiredTitle = ఈ లంకె గడువు ముగిసింది.
|
||||
downloadFirefox = { -firefox } ను దింపుకోండి
|
||||
legalTitle = { -send-short-brand } గోప్యతా నోటీసు
|
||||
legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నాటిది
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
|
||||
addFilesButton = ఎక్కించడానికి ఫైళ్ళను ఎంచుకోండి
|
||||
uploadButton = ఎక్కించు
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = ఫైళ్ళను లాగండి మరియు వదలండి
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = లేదా { $size } వరకు పంపడానికి నొక్కండి
|
||||
addPassword = సంకేతపదంతో రక్షించండి
|
||||
emailPlaceholder = ఈ ఈమెయిలును ఇవ్వండి
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = { $size } వరకు పంపడానికి ప్రవేశించండి
|
||||
signInOnlyButton = ప్రవేశించండి
|
||||
accountBenefitTitle = ఒక { -firefox } ఖాతాని సృష్టించండి లేదా ప్రవేశించండి
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = { $size } పరిమాణం ఫైళ్ళ వరకు పంచుకోండి
|
||||
accountBenefitDownloadCount = ఫైళ్లను ఎక్కువ మందితో పంచుకోండి
|
||||
accountBenefitSync = ఏదైనా పరికరం నుండి పంచుకున్న ఫైళ్ళను నిర్వహించండి
|
||||
signOut = నిష్క్రమించు
|
||||
okButton = సరే
|
||||
downloadingTitle = దింపుకుంటోంది
|
||||
noStreamsWarning = ఈ బ్రౌజర్ ఈ ఫైలును పెద్దగా డీక్రిప్ట్ చేయలేకపోవచ్చు.
|
||||
noStreamsOptionCopy = మరొక బ్రౌజర్లో తెరవడానికి లంకెను నకలు చేయండి
|
||||
noStreamsOptionFirefox = మా అభిమాన బ్రౌజర్ను ప్రయత్నించండి
|
||||
noStreamsOptionDownload = ఈ బ్రౌజర్తో కొనసాగించండి
|
||||
downloadFirefoxPromo = { -send-short-brand } క్రొత్త { -firefox } ద్వారా మీ ముందుకు తీసుకురాబడుతుంది.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = మీ ఫైలుకు లంకెను పంచుకోండి:
|
||||
shareLinkButton = లంకెను పంచుకోండి
|
||||
learnMore = ఇంకా తెలుసుకోండి.
|
||||
|
||||
146
public/locales/th/send.ftl
Normal file
146
public/locales/th/send.ftl
Normal file
@@ -0,0 +1,146 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteFeedback = ข้อคิดเห็น
|
||||
importingFile = กำลังนำเข้า…
|
||||
encryptingFile = กำลังเข้ารหัส…
|
||||
decryptingFile = กำลังถอดรหัส…
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
*[other] { $num } การดาวน์โหลด
|
||||
}
|
||||
timespanHours =
|
||||
{ $num ->
|
||||
*[other] { $num } ชั่วโมง
|
||||
}
|
||||
copiedUrl = คัดลอกแล้ว!
|
||||
unlockInputPlaceholder = รหัสผ่าน
|
||||
unlockButtonLabel = ปลดล็อก
|
||||
downloadButtonLabel = ดาวน์โหลด
|
||||
downloadFinish = การดาวน์โหลดเสร็จสมบูรณ์
|
||||
fileSizeProgress = ({ $partialSize } จาก { $totalSize })
|
||||
sendYourFilesLink = ลองใช้ Firefox Send
|
||||
errorPageHeader = มีบางอย่างผิดพลาด!
|
||||
fileTooBig = ไฟล์นั้นใหญ่เกินกว่าจะอัปโหลดได้ ไฟล์ที่จะอัปโหลดควรมีขนาดน้อยกว่า { $size }
|
||||
linkExpiredAlt = ลิงก์หมดอายุแล้ว
|
||||
notSupportedHeader = ไม่รองรับเบราว์เซอร์ของคุณ
|
||||
notSupportedLink = ทำไมจึงไม่รองรับเบราว์เซอร์ของฉัน?
|
||||
notSupportedOutdatedDetail = น่าเสียดายที่ Firefox รุ่นนี้ไม่สนับสนุนเทคโนโลยีเว็บที่ขับเคลื่อน Firefox Send คุณจะต้องอัปเดตเบราว์เซอร์ของคุณ
|
||||
updateFirefox = อัปเดต Firefox
|
||||
deletePopupCancel = ยกเลิก
|
||||
deleteButtonHover = ลบ
|
||||
footerLinkLegal = ข้อกฎหมาย
|
||||
footerLinkPrivacy = ความเป็นส่วนตัว
|
||||
footerLinkCookies = คุกกี้
|
||||
passwordTryAgain = รหัสผ่านไม่ถูกต้อง ลองอีกครั้ง
|
||||
javascriptRequired = Firefox Send จำเป็นต้องใช้ JavaScript
|
||||
whyJavascript = ทำไม Firefox Send จึงจำเป็นต้องใช้ JavaScript?
|
||||
enableJavascript = โปรดเปิดใช้งาน JavaScript แล้วลองอีกครั้ง
|
||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||
expiresHoursMinutes = { $hours } ชม. { $minutes } นาที
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes } นาที
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = ความยาวรหัสผ่านสูงสุด: { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = ไม่สามารถตั้งรหัสผ่านนี้ได้
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = Send
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = การแบ่งปันไฟล์ที่ง่ายและเป็นส่วนตัว
|
||||
introDescription = { -send-brand } ให้คุณแบ่งปันไฟล์ด้วยการเข้ารหัสจากต้นทางถึงปลายทางและลิงก์ที่หมดอายุโดยอัตโนมัติ คุณจึงสามารถเก็บสิ่งที่คุณแบ่งปันไว้เป็นส่วนตัวและตรวจสอบให้แน่ใจว่าข้อมูลของคุณจะไม่ออนไลน์ตลอดไป
|
||||
notifyUploadEncryptDone = ไฟล์ของคุณได้รับการเข้ารหัสและพร้อมส่ง
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = หมดอายุหลังจาก { $downloadCount } หรือ { $timespan }
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
*[other] { $num } นาที
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
*[other] { $num } วัน
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
*[other] { $num } สัปดาห์
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
*[other] { $num } ไฟล์
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
kb = KB
|
||||
# mebibyte abbreviation
|
||||
mb = MB
|
||||
# gibibyte abbreviation
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = ขนาดรวม: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = คัดลอกลิงก์เพื่อแบ่งปันไฟล์ของคุณ:
|
||||
copyLinkButton = คัดลอกลิงก์
|
||||
downloadTitle = ดาวน์โหลดไฟล์
|
||||
downloadDescription = ไฟล์นี้ถูกแบ่งปันผ่าน { -send-brand } พร้อมการเข้ารหัสจากต้นทางถึงปลายทางและลิงก์ที่หมดอายุโดยอัตโนมัติ
|
||||
trySendDescription = ลองใช้ { -send-brand } สำหรับการแบ่งปันไฟล์ที่ง่ายและปลอดภัย
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
*[other] สามารถอัปโหลดได้ครั้งละ { $count } ไฟล์เท่านั้น
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
*[other] สามารถอัปโหลดไฟล์เก็บถาวรได้เพียง { $count } ไฟล์เท่านั้น
|
||||
}
|
||||
expiredTitle = ลิงก์นี้หมดอายุแล้ว
|
||||
notSupportedDescription = { -send-brand } จะไม่ทำงานกับเบราว์เซอร์นี้ { -send-short-brand } จะทำงานได้ดีที่สุดกับ { -firefox } รุ่นล่าสุด และจะทำงานกับเบราว์เซอร์ส่วนใหญ่ที่เป็นรุ่นปัจจุบัน
|
||||
downloadFirefox = ดาวน์โหลด { -firefox }
|
||||
legalTitle = ประกาศความเป็นส่วนตัวของ { -send-short-brand }
|
||||
legalDateStamp = รุ่น 1.0 วันที่ 12 มีนาคม 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days } วัน { $hours } ชม. { $minutes } นาที
|
||||
addFilesButton = เลือกไฟล์ที่จะอัปโหลด
|
||||
uploadButton = อัปโหลด
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = ลากแล้วปล่อยไฟล์
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = หรือคลิกเพื่อส่งได้ถึง { $size }
|
||||
addPassword = ปกป้องด้วยรหัสผ่าน
|
||||
emailPlaceholder = ป้อนอีเมลของคุณ
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = ลงชื่อเข้าเพื่อส่งได้ถึง { $size }
|
||||
signInOnlyButton = ลงชื่อเข้า
|
||||
accountBenefitTitle = สร้างบัญชี { -firefox } หรือลงชื่อเข้า
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = แบ่งปันไฟล์สูงสุดถึง { $size }
|
||||
accountBenefitDownloadCount = แบ่งปันไฟล์กับผู้คนมากขึ้น
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
*[other] ให้ลิงก์ใช้งานได้นานถึง { $count } วัน
|
||||
}
|
||||
accountBenefitSync = จัดการไฟล์ที่แบ่งปันจากอุปกรณ์ใด ๆ
|
||||
accountBenefitMoz = เรียนรู้เกี่ยวกับบริการ { -mozilla } อื่น ๆ
|
||||
signOut = ลงชื่อออก
|
||||
okButton = ตกลง
|
||||
downloadingTitle = กำลังดาวน์โหลด
|
||||
noStreamsWarning = เบราว์เซอร์นี้อาจไม่สามารถถอดรหัสไฟล์ขนาดใหญ่เท่านี้ได้
|
||||
noStreamsOptionCopy = คัดลอกลิงก์เพื่อเปิดในเบราว์เซอร์อื่น
|
||||
noStreamsOptionFirefox = ลองเบราว์เซอร์โปรดของเรา
|
||||
noStreamsOptionDownload = ดำเนินการต่อด้วยเบราว์เซอร์นี้
|
||||
downloadFirefoxPromo = { -send-short-brand } สนับสนุนโดย { -firefox } โฉมใหม่
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = แบ่งปันลิงก์ไปยังไฟล์ของคุณ:
|
||||
shareLinkButton = แบ่งปันลิงก์
|
||||
# $name is the name of the file
|
||||
shareMessage = ดาวน์โหลด “{ $name }” ด้วย { -send-brand }: การแบ่งปันไฟล์ที่ง่ายและเป็นส่วนตัว
|
||||
trailheadPromo = มีวิธีปกป้องความเป็นส่วนตัวของคุณ เข้าร่วม Firefox
|
||||
learnMore = เรียนรู้เพิ่มเติม
|
||||
@@ -160,3 +160,5 @@ shareLinkDescription = Надішліть посилання на свій фа
|
||||
shareLinkButton = Поділитись посиланням
|
||||
# $name is the name of the file
|
||||
shareMessage = Завантажте “{ $name }” з { -send-brand }: простий та безпечний обмін файлами
|
||||
trailheadPromo = Існує спосіб захистити вашу приватність. Приєднуйтесь до Firefox.
|
||||
learnMore = Докладніше.
|
||||
|
||||
@@ -87,7 +87,7 @@ totalSize = Tổng kích thước: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Sao chép liên kết để chia sẻ tập tin của bạn:
|
||||
copyLinkButton = Sao chép liên kết
|
||||
downloadTitle = Tải tập tin
|
||||
downloadTitle = Tải xuống tập tin
|
||||
downloadDescription = Tập tin này đã được chia sẻ qua { -send-brand } với mã hóa đầu cuối và liên kết tự động hết hạn.
|
||||
trySendDescription = Hãy thử { -send-brand } để chia sẻ tập tin đơn giản, an toàn.
|
||||
# count will always be > 10
|
||||
|
||||
@@ -33,7 +33,7 @@ deleteButtonHover = ⴽⴽⵙ
|
||||
footerLinkLegal = ⵓⵙⴹⵉⴼ
|
||||
footerLinkPrivacy = ⵜⵉⵏⵏⵓⵜⵍⴰ
|
||||
footerLinkCookies = ⵉⴽⵓⴽⵉⵜⵏ
|
||||
passwordTryAgain = ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵓⵔ ⵢⵓⵖⴷⵏ. ⴰⵔⵎ ⴷⴰⵖ.
|
||||
passwordTryAgain = ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵓⵔ ⵢⵓⵖⵉⴷⵏ. ⴰⵔⵎ ⴷⴰⵖ.
|
||||
javascriptRequired = ⴷⴰ ⵉⵜⵜⴰⵙⵔ ⴼⴰⵢⵔⴼⵓⴽⵙ ⵙⵉⵏⴷ ⵊⴰⴼⴰⵙⴽⵔⵉⴱⵜ
|
||||
whyJavascript = ⵎⴰⵖⴼ ⴷⴰ ⵉⵜⵜⴰⵙⵔ ⴼⴰⵢⵔⴼⵓⴽⵙ ⵙⵉⵏⴷ ⵊⴰⴼⴰⵙⴽⵔⵉⴱⵜ?
|
||||
enableJavascript = ⵎⴽ ⵜⵓⴼⴰⵎ, ⵙⵏⵓⵛⵛⴳⴰⵜ ⵊⴰⴼⴰⵙⴽⵔⵉⴱⵜ, ⵜⴰⵔⵎⵎ ⴷⴰⵖ.
|
||||
@@ -95,7 +95,7 @@ copyLinkDescription = ⵙⵙⵏⵖⵍⴰⵜ ⴰⵙⵖⵏ ⴰⴼⴰⴷ ⴰⴷ ⵜ
|
||||
copyLinkButton = ⵙⵙⵏⵖⵍ ⴰⵙⵖⵏ
|
||||
downloadTitle = ⴰⴳⵎ ⵉⴼⵓⵢⵍⴰ
|
||||
downloadDescription = ⵉⵜⵜⵓⴱⴹⴰ ⵓⴼⴰⵢⵍⵓ ⴰ ⵙⴳ { -send-brand } ⵙ ⵓⵙⵙⵏⵜⵍ ⵙⴳ ⵜⴰⵎⴰ ⴰⵔ ⵜⴰⵎⴰ ⴷ ⵢⴰⵏ ⵓⵙⵖⵏ ⵏⵏⴰ ⵉⵜⵜⵎⵎⵜⴰⵜⵏ ⵙ ⵓⵡⵔⵎⴰⵏ.
|
||||
trySendDescription = ⴰⵔⵎ { -send-brand } ⵉ ⵓⴱⵟⵟⵓ ⴰⴼⵔⴰⵔ ⴷ ⵡⵓⴼⵔⵉⴳ.
|
||||
trySendDescription = ⴰⵔⵎⴰⵜ { -send-brand } ⵉ ⵓⴱⵟⵟⵓ ⴰⴼⵔⴰⵔ ⴷ ⵡⵓⴼⵔⵉⴳ ⵏ ⵉⴼⵓⵢⵍⴰ.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
@@ -126,7 +126,7 @@ addPassword = ⴰⵔⵢ ⵙ ⵜⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ
|
||||
emailPlaceholder = ⵙⵙⴽⵛⵎⴰⵜ ⵉⵎⴰⵢⵍ ⵏⵏⵓⵏ
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = ⴽⵛⵎ ⴰⴼⴰⴷ ⴰⴷ ⵜⴰⵣⵏⴷ ⴰⵔ { $size }
|
||||
signInButton = ⴽⵛⵎ/ⵣⵎⵎⴻⵎ
|
||||
signInOnlyButton = ⴽⵛⵎ
|
||||
accountBenefitTitle = ⵙⵏⴼⵍⵓⵍ ⴰⵎⵉⴹⴰⵏ ⵏ { -firefox } ⵏⵉⵖ ⵜⵣⵎⵎⴻⵎⴷ
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = ⴱⴹⵓ ⵉⴼⵓⵢⵍⴰ ⴰⵔ { $size }
|
||||
@@ -145,3 +145,11 @@ noStreamsWarning = ⵉⵣⵎⵔ ⵓⵎⵙⵙⴰⵔⴰ ⴰ ⴰⴷ ⵓⵔ ⵉⵖ
|
||||
noStreamsOptionCopy = ⵙⵙⵏⵖⵍⴰⵜ ⴰⵙⵖⵏ ⴰⴼⴰⴷ ⴰⴷ ⵜ ⵜⵕⵥⵎⵎ ⴳ ⴽⵔⴰ ⵏ ⵓⵎⵙⵙⴰⵔⴰ ⵢⴰⴹⵏ
|
||||
noStreamsOptionFirefox = ⴰⵔⵎⴰⵜ ⴰⵎⵙⵙⴰⵔⴰ ⵏⵏⵖ ⴰⵎⵓⴼⴰⵢ
|
||||
noStreamsOptionDownload = ⵙⵎⴷ ⵙ ⵓⵎⵙⵙⴰⵔⴰ ⴰ
|
||||
downloadFirefoxPromo = ⵉⵜⵜⵓⵙⵓⵎⵔ ⴰⵡⵏ { -send-short-brand } ⵙⴳ ⵖⵓⵔ { -firefox } ⴰⵎⴰⵢⵏⵓ ⴰⴽⴽⵯ.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = ⴱⴹⵓⵢⴰⵜ ⴰⵙⵖⵏ ⵖⵔ ⵓⴼⴰⵢⵍⵓ ⵏⵏⵓⵏ:
|
||||
shareLinkButton = ⴱⴹⵓ ⴰⵙⵖⵏ
|
||||
# $name is the name of the file
|
||||
shareMessage = ⴰⴳⵎⴰⵜ "{ $name }" ⵙ { -send-brand }: ⴰⴱⵟⵟⵓ ⴰⴼⵔⴰⵔ ⴷ ⵡⵓⵙⵍⵉⴳ ⵏ ⵉⴼⵓⵢⵍⴰ
|
||||
trailheadPromo = ⵜⵍⵍⴰ ⵢⴰⵜ ⵜⵖⴰⵔⴰⵙⵜ ⴰⴼⴰⴷ ⴰⴷ ⵜⴼⵔⴳⵎ ⵜⵉⵏⵏⵓⵜⵍⴰ ⵏⵏⵓⵏ. ⵍⴽⵎⴰⵜ ⴼⴰⵢⵔⴼⵓⴽⵙ.
|
||||
learnMore = ⵙⵙⵏ ⵓⴳⴳⴰⵔ.
|
||||
|
||||
@@ -55,7 +55,7 @@ introTitle = 簡單而私密的檔案共享服務
|
||||
introDescription = { -send-brand } 讓您可透過點對點加密的方式來分享檔案,並提供會自動失效的鏈結。這樣一來就可以保留分享時的隱私,也確保檔案不會永久保存於網路上。
|
||||
notifyUploadEncryptDone = 已加密您的檔案,可以傳送
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = { $downloadCount } 次下載或 { $timespan } 後失效
|
||||
archiveExpiryInfo = { $downloadCount } 或 { $timespan } 後失效
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
*[other] { $num } 分鐘
|
||||
|
||||
@@ -19,8 +19,8 @@ exec(cmd)
|
||||
const locales = Object.keys(summary)
|
||||
.filter(locale => {
|
||||
const loc = summary[locale];
|
||||
const hasMissing = loc.hasOwnProperty('missing');
|
||||
const hasErrors = loc.hasOwnProperty('errors');
|
||||
const hasMissing = Object.prototype.hasOwnProperty.call(loc, 'missing');
|
||||
const hasErrors = Object.prototype.hasOwnProperty.call(loc, 'errors');
|
||||
return !hasMissing && !hasErrors;
|
||||
})
|
||||
.sort();
|
||||
|
||||
@@ -33,7 +33,7 @@ function filterErrors(details) {
|
||||
.sort()
|
||||
.map(locale => {
|
||||
const data = details[locale]
|
||||
.filter(item => item.hasOwnProperty('error'))
|
||||
.filter(item => Object.prototype.hasOwnProperty.call(item, 'error'))
|
||||
.map(({ error }) => error);
|
||||
return { locale, data };
|
||||
})
|
||||
|
||||
13
scripts/sync-npm-dependencies.sh
Executable file
13
scripts/sync-npm-dependencies.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "checking package-lock.json for changes"
|
||||
IFS=' '
|
||||
read -ra G_PARAMS <<< "$HUSKY_GIT_PARAMS"
|
||||
PREV=${G_PARAMS[0]}
|
||||
NEXT=${G_PARAMS[1]}
|
||||
if [ "$PREV" != "$NEXT" ]; then
|
||||
DIFF=$(git diff $PREV $NEXT package-lock.json)
|
||||
if [ "$DIFF" != "" ]; then
|
||||
npm install
|
||||
fi
|
||||
fi
|
||||
@@ -3,7 +3,7 @@ const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const tests = require('../../test/frontend/routes');
|
||||
const express = require('express');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
const morgan = require('morgan');
|
||||
const config = require('../config');
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const Raven = require('raven');
|
||||
const Sentry = require('@sentry/node');
|
||||
const config = require('../config');
|
||||
const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
|
||||
if (config.sentry_dsn) {
|
||||
Raven.config(config.sentry_dsn).install();
|
||||
Sentry.init({ dsn: config.sentry_dsn });
|
||||
}
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -2,7 +2,7 @@ const assets = require('../../common/assets');
|
||||
const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const tests = require('../../test/frontend/routes');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
|
||||
module.exports = function(app, devServer) {
|
||||
assets.setMiddleware(devServer.middleware);
|
||||
|
||||
@@ -8,12 +8,10 @@ if (config.sentry_id) {
|
||||
//eslint-disable-next-line node/no-missing-require
|
||||
const version = require('../dist/version.json');
|
||||
sentry = `
|
||||
var RAVEN_CONFIG = {
|
||||
var SENTRY_CONFIG = {
|
||||
dsn: '${config.sentry_id}',
|
||||
release: '${version.version}',
|
||||
tags: {
|
||||
commit: '${version.commit}'
|
||||
},
|
||||
dataCallback: function (data) {
|
||||
beforeSend: function (data) {
|
||||
var hash = window.location.hash;
|
||||
if (hash) {
|
||||
return JSON.parse(JSON.stringify(data).replace(new RegExp(hash.slice(1), 'g'), ''));
|
||||
@@ -21,7 +19,6 @@ var RAVEN_CONFIG = {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
var SENTRY_ID = '${config.sentry_id}';
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { FluentBundle } = require('fluent');
|
||||
const { FluentBundle } = require('@fluent/bundle');
|
||||
const localesPath = path.resolve(__dirname, '../public/locales');
|
||||
const locales = fs.readdirSync(localesPath);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ const { availableLanguages } = require('../../package.json');
|
||||
const config = require('../config');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { negotiateLanguages } = require('fluent-langneg');
|
||||
const { negotiateLanguages } = require('@fluent/langneg');
|
||||
const langData = require('cldr-core/supplemental/likelySubtags.json');
|
||||
|
||||
// We return early in the middleware if the lang header is long.
|
||||
|
||||
@@ -67,7 +67,10 @@ module.exports = function(app) {
|
||||
}
|
||||
app.use(function(req, res, next) {
|
||||
res.set('Pragma', 'no-cache');
|
||||
res.set('Cache-Control', 'no-cache');
|
||||
res.set(
|
||||
'Cache-Control',
|
||||
'private, no-cache, no-store, must-revalidate, max-age=0'
|
||||
);
|
||||
next();
|
||||
});
|
||||
app.use(bodyParser.json());
|
||||
@@ -79,6 +82,7 @@ module.exports = function(app) {
|
||||
app.get('/error', language, pages.blank);
|
||||
app.get('/oauth', language, pages.blank);
|
||||
app.get('/legal', language, pages.legal);
|
||||
app.get('/login', language, pages.index);
|
||||
app.get('/app.webmanifest', language, require('./webmanifest'));
|
||||
app.get(`/download/:id${ID_REGEX}`, language, pages.download);
|
||||
app.get('/unsupported/:reason', language, pages.unsupported);
|
||||
@@ -104,6 +108,7 @@ module.exports = function(app) {
|
||||
app.post(`/api/info/:id${ID_REGEX}`, auth.owner, require('./info'));
|
||||
app.post('/api/metrics', require('./metrics'));
|
||||
app.get('/__version__', function(req, res) {
|
||||
// eslint-disable-next-line node/no-missing-require
|
||||
res.sendFile(require.resolve('../../dist/version.json'));
|
||||
});
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@ const storage = require('../storage');
|
||||
const config = require('../config');
|
||||
const mozlog = require('../log');
|
||||
const Limiter = require('../limiter');
|
||||
const wsStream = require('websocket-stream/stream');
|
||||
const fxa = require('../fxa');
|
||||
const { statUploadEvent } = require('../amplitude');
|
||||
const { encryptedSize } = require('../../app/utils');
|
||||
|
||||
const { Duplex } = require('stream');
|
||||
const { Transform } = require('stream');
|
||||
|
||||
const log = mozlog('send.upload');
|
||||
|
||||
@@ -76,25 +75,19 @@ module.exports = function(ws, req) {
|
||||
})
|
||||
);
|
||||
const limiter = new Limiter(encryptedSize(maxFileSize));
|
||||
const flowControl = new Duplex({
|
||||
read() {
|
||||
ws.resume();
|
||||
},
|
||||
write(chunk, encoding, callback) {
|
||||
const eof = new Transform({
|
||||
transform: function(chunk, encoding, callback) {
|
||||
if (chunk.length === 1 && chunk[0] === 0) {
|
||||
this.push(null);
|
||||
} else {
|
||||
if (!this.push(chunk)) {
|
||||
ws.pause();
|
||||
}
|
||||
this.push(chunk);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
});
|
||||
const wsStream = ws.constructor.createWebSocketStream(ws);
|
||||
|
||||
fileStream = wsStream(ws, { binary: true })
|
||||
.pipe(flowControl)
|
||||
.pipe(limiter); // limiter needs to be the last in the chain
|
||||
fileStream = wsStream.pipe(eof).pipe(limiter); // limiter needs to be the last in the chain
|
||||
|
||||
await storage.set(newId, fileStream, meta, timeLimit);
|
||||
|
||||
@@ -126,8 +119,8 @@ module.exports = function(ws, req) {
|
||||
error: e === 'limit' ? 413 : 500
|
||||
})
|
||||
);
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
ws.close();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ class GCSStorage {
|
||||
.pipe(
|
||||
this.bucket.file(id).createWriteStream({
|
||||
validation: false,
|
||||
resumable: false
|
||||
resumable: true
|
||||
})
|
||||
)
|
||||
.on('error', reject)
|
||||
|
||||
429
tailwind.config.js
Normal file
429
tailwind.config.js
Normal file
@@ -0,0 +1,429 @@
|
||||
const colors = {
|
||||
transparent: 'transparent',
|
||||
|
||||
black: '#22292f',
|
||||
'grey-darkest': '#4a4a4f',
|
||||
'grey-darker': '#606f7b',
|
||||
'grey-dark': '#8795a1',
|
||||
grey: '#B1B1B3',
|
||||
'grey-light': '#dae1e7',
|
||||
'grey-banner': '#f0f0f4',
|
||||
'grey-transparent': 'hsla(250, 13%, 9%, .2)',
|
||||
'grey-lighter': '#f1f5f8',
|
||||
'grey-lightest': '#F9F9FA',
|
||||
white: '#ffffff',
|
||||
|
||||
'red-darkest': '#3b0d0c',
|
||||
'red-darker': '#621b18',
|
||||
'red-dark': '#cc1f1a',
|
||||
red: '#e3342f',
|
||||
'red-light': '#ef5753',
|
||||
'red-lighter': '#f9acaa',
|
||||
'red-lightest': '#fcebea',
|
||||
|
||||
'orange-darkest': '#462a16',
|
||||
'orange-darker': '#613b1f',
|
||||
'orange-dark': '#de751f',
|
||||
orange: '#f6993f',
|
||||
'orange-light': '#faad63',
|
||||
'orange-lighter': '#fcd9b6',
|
||||
'orange-lightest': '#fff5eb',
|
||||
|
||||
'yellow-darkest': '#453411',
|
||||
'yellow-darker': '#684f1d',
|
||||
'yellow-dark': '#f2d024',
|
||||
yellow: '#ffed4a',
|
||||
'yellow-light': '#fff382',
|
||||
'yellow-lighter': '#fff9c2',
|
||||
'yellow-lightest': '#fcfbeb',
|
||||
|
||||
'green-darkest': '#003706',
|
||||
'green-darker': '#006504',
|
||||
'green-dark': '#058b00',
|
||||
green: '#12bc00',
|
||||
'green-light': '#51d88a',
|
||||
'green-lighter': '#a2f5bf',
|
||||
'green-lightest': '#e3fcec',
|
||||
|
||||
'teal-darkest': '#0d3331',
|
||||
'teal-darker': '#20504f',
|
||||
'teal-dark': '#38a89d',
|
||||
teal: '#4dc0b5',
|
||||
'teal-light': '#64d5ca',
|
||||
'teal-lighter': '#a0f0ed',
|
||||
'teal-lightest': '#e8fffe',
|
||||
|
||||
'blue-darkest': '#002275',
|
||||
'blue-darker': '#003eaa',
|
||||
'blue-dark': '#0060df',
|
||||
blue: '#0a84ff',
|
||||
'blue-light': '#6cb2eb',
|
||||
'blue-lighter': '#bcdefa',
|
||||
'blue-lightest': '#eff8ff',
|
||||
|
||||
'indigo-darkest': '#191e38',
|
||||
'indigo-darker': '#2f365f',
|
||||
'indigo-dark': '#5661b3',
|
||||
indigo: '#6574cd',
|
||||
'indigo-light': '#7886d7',
|
||||
'indigo-lighter': '#b2b7ff',
|
||||
'indigo-lightest': '#e6e8ff',
|
||||
|
||||
'purple-darkest': '#21183c',
|
||||
'purple-darker': '#382b5f',
|
||||
'purple-dark': '#794acf',
|
||||
purple: '#9561e2',
|
||||
'purple-light': '#a779e9',
|
||||
'purple-lighter': '#d6bbfc',
|
||||
'purple-lightest': '#f3ebff',
|
||||
|
||||
'pink-darkest': '#451225',
|
||||
'pink-darker': '#6f213f',
|
||||
'pink-dark': '#eb5286',
|
||||
pink: '#f66d9b',
|
||||
'pink-light': '#fa7ea8',
|
||||
'pink-lighter': '#ffbbca',
|
||||
'pink-lightest': '#ffebef',
|
||||
cloud: 'rgba(255, 255, 255, 0.8)',
|
||||
violet: 'hsl(258, 57%, 35%)'
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
colors: colors,
|
||||
screens: {
|
||||
sm: '576px',
|
||||
md: '768px',
|
||||
lg: '992px',
|
||||
xl: '1200px'
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [
|
||||
'Inter',
|
||||
'system-ui',
|
||||
'BlinkMacSystemFont',
|
||||
'-apple-system',
|
||||
'Segoe UI',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Cantarell',
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
'sans-serif'
|
||||
],
|
||||
serif: [
|
||||
'Constantia',
|
||||
'Lucida Bright',
|
||||
'Lucidabright',
|
||||
'Lucida Serif',
|
||||
'Lucida',
|
||||
'DejaVu Serif',
|
||||
'Bitstream Vera Serif',
|
||||
'Liberation Serif',
|
||||
'Georgia',
|
||||
'serif'
|
||||
],
|
||||
mono: [
|
||||
'Menlo',
|
||||
'Monaco',
|
||||
'Consolas',
|
||||
'Liberation Mono',
|
||||
'Courier New',
|
||||
'monospace'
|
||||
]
|
||||
},
|
||||
fontSize: {
|
||||
xs: '.75rem', // 12px
|
||||
sm: '.875rem', // 14px
|
||||
base: '1rem', // 16px
|
||||
lg: '1.125rem', // 18px
|
||||
xl: '1.25rem', // 20px
|
||||
'2xl': '1.5rem', // 24px
|
||||
'3xl': '2rem', // 32px
|
||||
'4xl': '2.25rem', // 36px
|
||||
'5xl': '3rem' // 48px
|
||||
},
|
||||
fontWeight: {
|
||||
hairline: 100,
|
||||
thin: 200,
|
||||
light: 300,
|
||||
normal: 400,
|
||||
medium: 500,
|
||||
semibold: 600,
|
||||
bold: 700,
|
||||
extrabold: 800,
|
||||
black: 900
|
||||
},
|
||||
lineHeight: {
|
||||
none: 1,
|
||||
tight: 1.25,
|
||||
normal: 1.5,
|
||||
loose: 1.75
|
||||
},
|
||||
letterSpacing: {
|
||||
tight: '-0.05em',
|
||||
normal: '0',
|
||||
wide: '0.05em'
|
||||
},
|
||||
textColor: colors,
|
||||
backgroundColor: colors,
|
||||
backgroundSize: {
|
||||
auto: 'auto',
|
||||
cover: 'cover',
|
||||
contain: 'contain'
|
||||
},
|
||||
borderWidth: {
|
||||
default: '1px',
|
||||
'0': '0',
|
||||
'2': '2px',
|
||||
'4': '4px',
|
||||
'8': '8px'
|
||||
},
|
||||
borderColor: global.Object.assign(
|
||||
{ default: colors['grey-light'] },
|
||||
colors
|
||||
),
|
||||
borderRadius: {
|
||||
none: '0',
|
||||
sm: '.125rem',
|
||||
default: '.25rem',
|
||||
lg: '.5rem',
|
||||
xl: '1rem',
|
||||
full: '9999px'
|
||||
},
|
||||
width: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'48': '12rem',
|
||||
'64': '16rem',
|
||||
'128': '32rem',
|
||||
'1/2': '50%',
|
||||
'1/3': '33.33333%',
|
||||
'2/3': '66.66667%',
|
||||
'1/4': '25%',
|
||||
'3/4': '75%',
|
||||
'1/5': '20%',
|
||||
'2/5': '40%',
|
||||
'3/5': '60%',
|
||||
'4/5': '80%',
|
||||
'1/6': '16.66667%',
|
||||
'5/6': '83.33333%',
|
||||
full: '100%',
|
||||
screen: '100vw'
|
||||
},
|
||||
height: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'48': '12rem',
|
||||
'64': '16rem',
|
||||
full: '100%',
|
||||
screen: '100vh'
|
||||
},
|
||||
minWidth: {
|
||||
'0': '0',
|
||||
full: '100%'
|
||||
},
|
||||
minHeight: {
|
||||
'0': '0',
|
||||
full: '100%',
|
||||
screen: '100vh'
|
||||
},
|
||||
maxWidth: {
|
||||
xs: '20rem',
|
||||
sm: '30rem',
|
||||
md: '40rem',
|
||||
lg: '50rem',
|
||||
xl: '60rem',
|
||||
'2xl': '70rem',
|
||||
'3xl': '80rem',
|
||||
'4xl': '90rem',
|
||||
'5xl': '100rem',
|
||||
full: '100%'
|
||||
},
|
||||
maxHeight: {
|
||||
full: '100%',
|
||||
'half-screen': '50vh',
|
||||
screen: '100vh'
|
||||
},
|
||||
padding: {
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem'
|
||||
},
|
||||
margin: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'-px': '-1px',
|
||||
'-1': '-0.25rem',
|
||||
'-2': '-0.5rem',
|
||||
'-3': '-0.75rem',
|
||||
'-4': '-1rem',
|
||||
'-5': '-1.25rem',
|
||||
'-6': '-1.5rem',
|
||||
'-8': '-2rem',
|
||||
'-10': '-2.5rem',
|
||||
'-12': '-3rem',
|
||||
'-16': '-4rem',
|
||||
'-20': '-5rem',
|
||||
'-24': '-6rem',
|
||||
'-32': '-8rem'
|
||||
},
|
||||
boxShadow: {
|
||||
default: '0 2px 4px 0 rgba(0,0,0,0.10)',
|
||||
md: '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08)',
|
||||
lg: '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)',
|
||||
inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.06)',
|
||||
outline: '0 0 0 3px rgba(52,144,220,0.5)',
|
||||
none: 'none',
|
||||
cloud: '0 0 5rem 5rem white',
|
||||
btn:
|
||||
'inset 0 -6px 12px 0 rgba(0,70,144,0.25), 0 4px 6px 0 rgba(34,0,51,0.04), 0 1px 10px 0 rgba(7,48,114,0.12), 0 2px 8px -1px rgba(14,13,26,0.08)'
|
||||
},
|
||||
opacity: {
|
||||
'0': '0',
|
||||
'25': '.25',
|
||||
'50': '.5',
|
||||
'75': '.75',
|
||||
'100': '1'
|
||||
},
|
||||
fill: {
|
||||
current: 'currentColor'
|
||||
},
|
||||
stroke: {
|
||||
current: 'currentColor'
|
||||
},
|
||||
|
||||
zIndex: {
|
||||
auto: 'auto',
|
||||
'0': 0,
|
||||
'10': 10,
|
||||
'20': 20,
|
||||
'30': 30,
|
||||
'40': 40,
|
||||
'50': 50
|
||||
}
|
||||
},
|
||||
|
||||
variants: {
|
||||
appearance: ['responsive'],
|
||||
backgroundAttachment: ['responsive'],
|
||||
backgroundColor: ['responsive', 'hover', 'focus'],
|
||||
backgroundPosition: ['responsive'],
|
||||
backgroundRepeat: ['responsive'],
|
||||
backgroundSize: ['responsive'],
|
||||
borderCollapse: [],
|
||||
borderColor: ['responsive', 'hover', 'focus'],
|
||||
borderRadius: ['responsive'],
|
||||
borderStyle: ['responsive'],
|
||||
borderWidth: ['responsive'],
|
||||
cursor: ['responsive'],
|
||||
display: ['responsive'],
|
||||
flexDirection: ['responsive'],
|
||||
flexWrap: ['responsive'],
|
||||
alignItems: ['responsive'],
|
||||
alignSelf: ['responsive'],
|
||||
alignContent: ['responsive'],
|
||||
justifyContent: ['responsive'],
|
||||
flex: ['responsive'],
|
||||
flexGrow: ['responsive'],
|
||||
flexShrink: ['responsive'],
|
||||
float: ['responsive'],
|
||||
fontFamily: ['responsive'],
|
||||
fontWeight: ['responsive', 'hover', 'focus'],
|
||||
height: ['responsive'],
|
||||
lineHeight: ['responsive'],
|
||||
listStylePosition: ['responsive'],
|
||||
listStyleType: ['responsive'],
|
||||
margin: ['responsive'],
|
||||
maxHeight: ['responsive'],
|
||||
maxWidth: ['responsive'],
|
||||
minHeight: ['responsive'],
|
||||
minWidth: ['responsive'],
|
||||
negativeMargin: ['responsive'],
|
||||
opacity: ['responsive', 'hover'],
|
||||
outline: ['focus'],
|
||||
overflow: ['responsive'],
|
||||
padding: ['responsive'],
|
||||
pointerEvents: ['responsive'],
|
||||
position: ['responsive'],
|
||||
inset: ['responsive'],
|
||||
resize: ['responsive'],
|
||||
boxShadow: ['responsive', 'hover', 'focus'],
|
||||
fill: [],
|
||||
stroke: [],
|
||||
tableLayout: ['responsive'],
|
||||
textAlign: ['responsive'],
|
||||
textColor: ['responsive', 'hover', 'focus'],
|
||||
fontSize: ['responsive'],
|
||||
fontStyle: ['responsive', 'hover', 'focus'],
|
||||
fontSmoothing: ['responsive', 'hover', 'focus'],
|
||||
textDecoration: ['responsive', 'hover', 'focus'],
|
||||
textTransform: ['responsive', 'hover', 'focus'],
|
||||
letterSpacing: ['responsive'],
|
||||
userSelect: ['responsive'],
|
||||
verticalAlign: ['responsive'],
|
||||
visibility: ['responsive'],
|
||||
whitespace: ['responsive'],
|
||||
wordBreak: ['responsive'],
|
||||
width: ['responsive'],
|
||||
zIndex: ['responsive']
|
||||
},
|
||||
corePlugins: {
|
||||
container: false
|
||||
},
|
||||
plugins: []
|
||||
};
|
||||
933
tailwind.js
933
tailwind.js
@@ -1,933 +0,0 @@
|
||||
/*
|
||||
|
||||
Tailwind - The Utility-First CSS Framework
|
||||
|
||||
A project by Adam Wathan (@adamwathan), Jonathan Reinink (@reinink),
|
||||
David Hemphill (@davidhemphill) and Steve Schoger (@steveschoger).
|
||||
|
||||
Welcome to the Tailwind config file. This is where you can customize
|
||||
Tailwind specifically for your project. Don't be intimidated by the
|
||||
length of this file. It's really just a big JavaScript object and
|
||||
we've done our very best to explain each section.
|
||||
|
||||
View the full documentation at https://tailwindcss.com.
|
||||
|
||||
|
||||
|-------------------------------------------------------------------------------
|
||||
| The default config
|
||||
|-------------------------------------------------------------------------------
|
||||
|
|
||||
| This variable contains the default Tailwind config. You don't have
|
||||
| to use it, but it can sometimes be helpful to have available. For
|
||||
| example, you may choose to merge your custom configuration
|
||||
| values with some of the Tailwind defaults.
|
||||
|
|
||||
*/
|
||||
|
||||
// let defaultConfig = require('tailwindcss/defaultConfig')()
|
||||
|
||||
/*
|
||||
|-------------------------------------------------------------------------------
|
||||
| Colors https://tailwindcss.com/docs/colors
|
||||
|-------------------------------------------------------------------------------
|
||||
|
|
||||
| Here you can specify the colors used in your project. To get you started,
|
||||
| we've provided a generous palette of great looking colors that are perfect
|
||||
| for prototyping, but don't hesitate to change them for your project. You
|
||||
| own these colors, nothing will break if you change everything about them.
|
||||
|
|
||||
| We've used literal color names ("red", "blue", etc.) for the default
|
||||
| palette, but if you'd rather use functional names like "primary" and
|
||||
| "secondary", or even a numeric scale like "100" and "200", go for it.
|
||||
|
|
||||
*/
|
||||
|
||||
const colors = {
|
||||
transparent: 'transparent',
|
||||
|
||||
black: '#22292f',
|
||||
'grey-darkest': '#4a4a4f',
|
||||
'grey-darker': '#606f7b',
|
||||
'grey-dark': '#8795a1',
|
||||
grey: '#B1B1B3',
|
||||
'grey-light': '#dae1e7',
|
||||
'grey-banner': '#f0f0f4',
|
||||
'grey-transparent': 'hsla(250, 13%, 9%, .2)',
|
||||
'grey-lighter': '#f1f5f8',
|
||||
'grey-lightest': '#F9F9FA',
|
||||
white: '#ffffff',
|
||||
|
||||
'red-darkest': '#3b0d0c',
|
||||
'red-darker': '#621b18',
|
||||
'red-dark': '#cc1f1a',
|
||||
red: '#e3342f',
|
||||
'red-light': '#ef5753',
|
||||
'red-lighter': '#f9acaa',
|
||||
'red-lightest': '#fcebea',
|
||||
|
||||
'orange-darkest': '#462a16',
|
||||
'orange-darker': '#613b1f',
|
||||
'orange-dark': '#de751f',
|
||||
orange: '#f6993f',
|
||||
'orange-light': '#faad63',
|
||||
'orange-lighter': '#fcd9b6',
|
||||
'orange-lightest': '#fff5eb',
|
||||
|
||||
'yellow-darkest': '#453411',
|
||||
'yellow-darker': '#684f1d',
|
||||
'yellow-dark': '#f2d024',
|
||||
yellow: '#ffed4a',
|
||||
'yellow-light': '#fff382',
|
||||
'yellow-lighter': '#fff9c2',
|
||||
'yellow-lightest': '#fcfbeb',
|
||||
|
||||
'green-darkest': '#003706',
|
||||
'green-darker': '#006504',
|
||||
'green-dark': '#058b00',
|
||||
green: '#12bc00',
|
||||
'green-light': '#51d88a',
|
||||
'green-lighter': '#a2f5bf',
|
||||
'green-lightest': '#e3fcec',
|
||||
|
||||
'teal-darkest': '#0d3331',
|
||||
'teal-darker': '#20504f',
|
||||
'teal-dark': '#38a89d',
|
||||
teal: '#4dc0b5',
|
||||
'teal-light': '#64d5ca',
|
||||
'teal-lighter': '#a0f0ed',
|
||||
'teal-lightest': '#e8fffe',
|
||||
|
||||
'blue-darkest': '#002275',
|
||||
'blue-darker': '#003eaa',
|
||||
'blue-dark': '#0060df',
|
||||
blue: '#0a84ff',
|
||||
'blue-light': '#6cb2eb',
|
||||
'blue-lighter': '#bcdefa',
|
||||
'blue-lightest': '#eff8ff',
|
||||
|
||||
'indigo-darkest': '#191e38',
|
||||
'indigo-darker': '#2f365f',
|
||||
'indigo-dark': '#5661b3',
|
||||
indigo: '#6574cd',
|
||||
'indigo-light': '#7886d7',
|
||||
'indigo-lighter': '#b2b7ff',
|
||||
'indigo-lightest': '#e6e8ff',
|
||||
|
||||
'purple-darkest': '#21183c',
|
||||
'purple-darker': '#382b5f',
|
||||
'purple-dark': '#794acf',
|
||||
purple: '#9561e2',
|
||||
'purple-light': '#a779e9',
|
||||
'purple-lighter': '#d6bbfc',
|
||||
'purple-lightest': '#f3ebff',
|
||||
|
||||
'pink-darkest': '#451225',
|
||||
'pink-darker': '#6f213f',
|
||||
'pink-dark': '#eb5286',
|
||||
pink: '#f66d9b',
|
||||
'pink-light': '#fa7ea8',
|
||||
'pink-lighter': '#ffbbca',
|
||||
'pink-lightest': '#ffebef',
|
||||
cloud: 'rgba(255, 255, 255, 0.8)',
|
||||
violet: 'hsl(258, 57%, 35%)'
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Colors https://tailwindcss.com/docs/colors
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| The color palette defined above is also assigned to the "colors" key of
|
||||
| your Tailwind config. This makes it easy to access them in your CSS
|
||||
| using Tailwind's config helper. For example:
|
||||
|
|
||||
| .error { color: config('colors.red') }
|
||||
|
|
||||
*/
|
||||
|
||||
colors: colors,
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Screens https://tailwindcss.com/docs/responsive-design
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Screens in Tailwind are translated to CSS media queries. They define the
|
||||
| responsive breakpoints for your project. By default Tailwind takes a
|
||||
| "mobile first" approach, where each screen size represents a minimum
|
||||
| viewport width. Feel free to have as few or as many screens as you
|
||||
| want, naming them in whatever way you'd prefer for your project.
|
||||
|
|
||||
| Tailwind also allows for more complex screen definitions, which can be
|
||||
| useful in certain situations. Be sure to see the full responsive
|
||||
| documentation for a complete list of options.
|
||||
|
|
||||
| Class name: .{screen}:{utility}
|
||||
|
|
||||
*/
|
||||
|
||||
screens: {
|
||||
sm: '576px',
|
||||
md: '768px',
|
||||
lg: '992px',
|
||||
xl: '1200px'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Fonts https://tailwindcss.com/docs/fonts
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your project's font stack, or font families.
|
||||
| Keep in mind that Tailwind doesn't actually load any fonts for you.
|
||||
| If you're using custom fonts you'll need to import them prior to
|
||||
| defining them here.
|
||||
|
|
||||
| By default we provide a native font stack that works remarkably well on
|
||||
| any device or OS you're using, since it just uses the default fonts
|
||||
| provided by the platform.
|
||||
|
|
||||
| Class name: .font-{name}
|
||||
|
|
||||
*/
|
||||
|
||||
fonts: {
|
||||
sans: [
|
||||
'Inter',
|
||||
'system-ui',
|
||||
'BlinkMacSystemFont',
|
||||
'-apple-system',
|
||||
'Segoe UI',
|
||||
'Roboto',
|
||||
'Oxygen',
|
||||
'Ubuntu',
|
||||
'Cantarell',
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
'sans-serif'
|
||||
],
|
||||
serif: [
|
||||
'Constantia',
|
||||
'Lucida Bright',
|
||||
'Lucidabright',
|
||||
'Lucida Serif',
|
||||
'Lucida',
|
||||
'DejaVu Serif',
|
||||
'Bitstream Vera Serif',
|
||||
'Liberation Serif',
|
||||
'Georgia',
|
||||
'serif'
|
||||
],
|
||||
mono: [
|
||||
'Menlo',
|
||||
'Monaco',
|
||||
'Consolas',
|
||||
'Liberation Mono',
|
||||
'Courier New',
|
||||
'monospace'
|
||||
]
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Text sizes https://tailwindcss.com/docs/text-sizing
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your text sizes. Name these in whatever way
|
||||
| makes the most sense to you. We use size names by default, but
|
||||
| you're welcome to use a numeric scale or even something else
|
||||
| entirely.
|
||||
|
|
||||
| By default Tailwind uses the "rem" unit type for most measurements.
|
||||
| This allows you to set a root font size which all other sizes are
|
||||
| then based on. That said, you are free to use whatever units you
|
||||
| prefer, be it rems, ems, pixels or other.
|
||||
|
|
||||
| Class name: .text-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
textSizes: {
|
||||
xs: '.75rem', // 12px
|
||||
sm: '.875rem', // 14px
|
||||
base: '1rem', // 16px
|
||||
lg: '1.125rem', // 18px
|
||||
xl: '1.25rem', // 20px
|
||||
'2xl': '1.5rem', // 24px
|
||||
'3xl': '1.875rem', // 30px
|
||||
'4xl': '2.25rem', // 36px
|
||||
'5xl': '3rem' // 48px
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Font weights https://tailwindcss.com/docs/font-weight
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your font weights. We've provided a list of
|
||||
| common font weight names with their respective numeric scale values
|
||||
| to get you started. It's unlikely that your project will require
|
||||
| all of these, so we recommend removing those you don't need.
|
||||
|
|
||||
| Class name: .font-{weight}
|
||||
|
|
||||
*/
|
||||
|
||||
fontWeights: {
|
||||
hairline: 100,
|
||||
thin: 200,
|
||||
light: 300,
|
||||
normal: 400,
|
||||
medium: 500,
|
||||
semibold: 600,
|
||||
bold: 700,
|
||||
extrabold: 800,
|
||||
black: 900
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Leading (line height) https://tailwindcss.com/docs/line-height
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your line height values, or as we call
|
||||
| them in Tailwind, leadings.
|
||||
|
|
||||
| Class name: .leading-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
leading: {
|
||||
none: 1,
|
||||
tight: 1.25,
|
||||
normal: 1.5,
|
||||
loose: 1.75
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Tracking (letter spacing) https://tailwindcss.com/docs/letter-spacing
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your letter spacing values, or as we call
|
||||
| them in Tailwind, tracking.
|
||||
|
|
||||
| Class name: .tracking-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
tracking: {
|
||||
tight: '-0.05em',
|
||||
normal: '0',
|
||||
wide: '0.05em'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Text colors https://tailwindcss.com/docs/text-color
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your text colors. By default these use the
|
||||
| color palette we defined above, however you're welcome to set these
|
||||
| independently if that makes sense for your project.
|
||||
|
|
||||
| Class name: .text-{color}
|
||||
|
|
||||
*/
|
||||
|
||||
textColors: colors,
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Background colors https://tailwindcss.com/docs/background-color
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your background colors. By default these use
|
||||
| the color palette we defined above, however you're welcome to set
|
||||
| these independently if that makes sense for your project.
|
||||
|
|
||||
| Class name: .bg-{color}
|
||||
|
|
||||
*/
|
||||
|
||||
backgroundColors: colors,
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Background sizes https://tailwindcss.com/docs/background-size
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your background sizes. We provide some common
|
||||
| values that are useful in most projects, but feel free to add other sizes
|
||||
| that are specific to your project here as well.
|
||||
|
|
||||
| Class name: .bg-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
backgroundSize: {
|
||||
auto: 'auto',
|
||||
cover: 'cover',
|
||||
contain: 'contain'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Border widths https://tailwindcss.com/docs/border-width
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your border widths. Take note that border
|
||||
| widths require a special "default" value set as well. This is the
|
||||
| width that will be used when you do not specify a border width.
|
||||
|
|
||||
| Class name: .border{-side?}{-width?}
|
||||
|
|
||||
*/
|
||||
|
||||
borderWidths: {
|
||||
default: '1px',
|
||||
'0': '0',
|
||||
'2': '2px',
|
||||
'4': '4px',
|
||||
'8': '8px'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Border colors https://tailwindcss.com/docs/border-color
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your border colors. By default these use the
|
||||
| color palette we defined above, however you're welcome to set these
|
||||
| independently if that makes sense for your project.
|
||||
|
|
||||
| Take note that border colors require a special "default" value set
|
||||
| as well. This is the color that will be used when you do not
|
||||
| specify a border color.
|
||||
|
|
||||
| Class name: .border-{color}
|
||||
|
|
||||
*/
|
||||
|
||||
borderColors: global.Object.assign({ default: colors['grey-light'] }, colors),
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Border radius https://tailwindcss.com/docs/border-radius
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your border radius values. If a `default` radius
|
||||
| is provided, it will be made available as the non-suffixed `.rounded`
|
||||
| utility.
|
||||
|
|
||||
| If your scale includes a `0` value to reset already rounded corners, it's
|
||||
| a good idea to put it first so other values are able to override it.
|
||||
|
|
||||
| Class name: .rounded{-side?}{-size?}
|
||||
|
|
||||
*/
|
||||
|
||||
borderRadius: {
|
||||
none: '0',
|
||||
sm: '.125rem',
|
||||
default: '.25rem',
|
||||
lg: '.5rem',
|
||||
xl: '1rem',
|
||||
full: '9999px'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Width https://tailwindcss.com/docs/width
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your width utility sizes. These can be
|
||||
| percentage based, pixels, rems, or any other units. By default
|
||||
| we provide a sensible rem based numeric scale, a percentage
|
||||
| based fraction scale, plus some other common use-cases. You
|
||||
| can, of course, modify these values as needed.
|
||||
|
|
||||
|
|
||||
| It's also worth mentioning that Tailwind automatically escapes
|
||||
| invalid CSS class name characters, which allows you to have
|
||||
| awesome classes like .w-2/3.
|
||||
|
|
||||
| Class name: .w-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
width: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'48': '12rem',
|
||||
'64': '16rem',
|
||||
'128': '32rem',
|
||||
'1/2': '50%',
|
||||
'1/3': '33.33333%',
|
||||
'2/3': '66.66667%',
|
||||
'1/4': '25%',
|
||||
'3/4': '75%',
|
||||
'1/5': '20%',
|
||||
'2/5': '40%',
|
||||
'3/5': '60%',
|
||||
'4/5': '80%',
|
||||
'1/6': '16.66667%',
|
||||
'5/6': '83.33333%',
|
||||
full: '100%',
|
||||
screen: '100vw'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Height https://tailwindcss.com/docs/height
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your height utility sizes. These can be
|
||||
| percentage based, pixels, rems, or any other units. By default
|
||||
| we provide a sensible rem based numeric scale plus some other
|
||||
| common use-cases. You can, of course, modify these values as
|
||||
| needed.
|
||||
|
|
||||
| Class name: .h-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
height: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'48': '12rem',
|
||||
'64': '16rem',
|
||||
full: '100%',
|
||||
screen: '100vh'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Minimum width https://tailwindcss.com/docs/min-width
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your minimum width utility sizes. These can
|
||||
| be percentage based, pixels, rems, or any other units. We provide a
|
||||
| couple common use-cases by default. You can, of course, modify
|
||||
| these values as needed.
|
||||
|
|
||||
| Class name: .min-w-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
minWidth: {
|
||||
'0': '0',
|
||||
full: '100%'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Minimum height https://tailwindcss.com/docs/min-height
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your minimum height utility sizes. These can
|
||||
| be percentage based, pixels, rems, or any other units. We provide a
|
||||
| few common use-cases by default. You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .min-h-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
minHeight: {
|
||||
'0': '0',
|
||||
full: '100%',
|
||||
screen: '100vh'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Maximum width https://tailwindcss.com/docs/max-width
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your maximum width utility sizes. These can
|
||||
| be percentage based, pixels, rems, or any other units. By default
|
||||
| we provide a sensible rem based scale and a "full width" size,
|
||||
| which is basically a reset utility. You can, of course,
|
||||
| modify these values as needed.
|
||||
|
|
||||
| Class name: .max-w-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
maxWidth: {
|
||||
xs: '20rem',
|
||||
sm: '30rem',
|
||||
md: '40rem',
|
||||
lg: '50rem',
|
||||
xl: '60rem',
|
||||
'2xl': '70rem',
|
||||
'3xl': '80rem',
|
||||
'4xl': '90rem',
|
||||
'5xl': '100rem',
|
||||
full: '100%'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Maximum height https://tailwindcss.com/docs/max-height
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your maximum height utility sizes. These can
|
||||
| be percentage based, pixels, rems, or any other units. We provide a
|
||||
| couple common use-cases by default. You can, of course, modify
|
||||
| these values as needed.
|
||||
|
|
||||
| Class name: .max-h-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
maxHeight: {
|
||||
full: '100%',
|
||||
'half-screen': '50vh',
|
||||
screen: '100vh'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Padding https://tailwindcss.com/docs/padding
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your padding utility sizes. These can be
|
||||
| percentage based, pixels, rems, or any other units. By default we
|
||||
| provide a sensible rem based numeric scale plus a couple other
|
||||
| common use-cases like "1px". You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .p{side?}-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
padding: {
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Margin https://tailwindcss.com/docs/margin
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your margin utility sizes. These can be
|
||||
| percentage based, pixels, rems, or any other units. By default we
|
||||
| provide a sensible rem based numeric scale plus a couple other
|
||||
| common use-cases like "1px". You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .m{side?}-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
margin: {
|
||||
auto: 'auto',
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Negative margin https://tailwindcss.com/docs/negative-margin
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your negative margin utility sizes. These can
|
||||
| be percentage based, pixels, rems, or any other units. By default we
|
||||
| provide matching values to the padding scale since these utilities
|
||||
| generally get used together. You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .-m{side?}-{size}
|
||||
|
|
||||
*/
|
||||
|
||||
negativeMargin: {
|
||||
px: '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Shadows https://tailwindcss.com/docs/shadows
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your shadow utilities. As you can see from
|
||||
| the defaults we provide, it's possible to apply multiple shadows
|
||||
| per utility using comma separation.
|
||||
|
|
||||
| If a `default` shadow is provided, it will be made available as the non-
|
||||
| suffixed `.shadow` utility.
|
||||
|
|
||||
| Class name: .shadow-{size?}
|
||||
|
|
||||
*/
|
||||
|
||||
shadows: {
|
||||
default: '0 2px 4px 0 rgba(0,0,0,0.10)',
|
||||
md: '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08)',
|
||||
lg: '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)',
|
||||
inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.06)',
|
||||
outline: '0 0 0 3px rgba(52,144,220,0.5)',
|
||||
none: 'none',
|
||||
cloud: '0 0 5rem 5rem white',
|
||||
btn:
|
||||
'inset 0 -6px 12px 0 rgba(0,70,144,0.25), 0 4px 6px 0 rgba(34,0,51,0.04), 0 1px 10px 0 rgba(7,48,114,0.12), 0 2px 8px -1px rgba(14,13,26,0.08)'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Z-index https://tailwindcss.com/docs/z-index
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your z-index utility values. By default we
|
||||
| provide a sensible numeric scale. You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .z-{index}
|
||||
|
|
||||
*/
|
||||
|
||||
zIndex: {
|
||||
auto: 'auto',
|
||||
'0': 0,
|
||||
'10': 10,
|
||||
'20': 20,
|
||||
'30': 30,
|
||||
'40': 40,
|
||||
'50': 50
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Opacity https://tailwindcss.com/docs/opacity
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your opacity utility values. By default we
|
||||
| provide a sensible numeric scale. You can, of course, modify these
|
||||
| values as needed.
|
||||
|
|
||||
| Class name: .opacity-{name}
|
||||
|
|
||||
*/
|
||||
|
||||
opacity: {
|
||||
'0': '0',
|
||||
'25': '.25',
|
||||
'50': '.5',
|
||||
'75': '.75',
|
||||
'100': '1'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| SVG fill https://tailwindcss.com/docs/svg
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your SVG fill colors. By default we just provide
|
||||
| `fill-current` which sets the fill to the current text color. This lets you
|
||||
| specify a fill color using existing text color utilities and helps keep the
|
||||
| generated CSS file size down.
|
||||
|
|
||||
| Class name: .fill-{name}
|
||||
|
|
||||
*/
|
||||
|
||||
svgFill: {
|
||||
current: 'currentColor'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| SVG stroke https://tailwindcss.com/docs/svg
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you define your SVG stroke colors. By default we just provide
|
||||
| `stroke-current` which sets the stroke to the current text color. This lets
|
||||
| you specify a stroke color using existing text color utilities and helps
|
||||
| keep the generated CSS file size down.
|
||||
|
|
||||
| Class name: .stroke-{name}
|
||||
|
|
||||
*/
|
||||
|
||||
svgStroke: {
|
||||
current: 'currentColor'
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Modules https://tailwindcss.com/docs/configuration#modules
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you control which modules are generated and what variants are
|
||||
| generated for each of those modules.
|
||||
|
|
||||
| Currently supported variants:
|
||||
| - responsive
|
||||
| - hover
|
||||
| - focus
|
||||
| - active
|
||||
| - group-hover
|
||||
|
|
||||
| To disable a module completely, use `false` instead of an array.
|
||||
|
|
||||
*/
|
||||
|
||||
modules: {
|
||||
appearance: ['responsive'],
|
||||
backgroundAttachment: ['responsive'],
|
||||
backgroundColors: ['responsive', 'hover', 'focus'],
|
||||
backgroundPosition: ['responsive'],
|
||||
backgroundRepeat: ['responsive'],
|
||||
backgroundSize: ['responsive'],
|
||||
borderCollapse: [],
|
||||
borderColors: ['responsive', 'hover', 'focus'],
|
||||
borderRadius: ['responsive'],
|
||||
borderStyle: ['responsive'],
|
||||
borderWidths: ['responsive'],
|
||||
cursor: ['responsive'],
|
||||
display: ['responsive'],
|
||||
flexbox: ['responsive'],
|
||||
float: ['responsive'],
|
||||
fonts: ['responsive'],
|
||||
fontWeights: ['responsive', 'hover', 'focus'],
|
||||
height: ['responsive'],
|
||||
leading: ['responsive'],
|
||||
lists: ['responsive'],
|
||||
margin: ['responsive'],
|
||||
maxHeight: ['responsive'],
|
||||
maxWidth: ['responsive'],
|
||||
minHeight: ['responsive'],
|
||||
minWidth: ['responsive'],
|
||||
negativeMargin: ['responsive'],
|
||||
opacity: ['responsive', 'hover'],
|
||||
outline: ['focus'],
|
||||
overflow: ['responsive'],
|
||||
padding: ['responsive'],
|
||||
pointerEvents: ['responsive'],
|
||||
position: ['responsive'],
|
||||
resize: ['responsive'],
|
||||
shadows: ['responsive', 'hover', 'focus'],
|
||||
svgFill: [],
|
||||
svgStroke: [],
|
||||
tableLayout: ['responsive'],
|
||||
textAlign: ['responsive'],
|
||||
textColors: ['responsive', 'hover', 'focus'],
|
||||
textSizes: ['responsive'],
|
||||
textStyle: ['responsive', 'hover', 'focus'],
|
||||
tracking: ['responsive'],
|
||||
userSelect: ['responsive'],
|
||||
verticalAlign: ['responsive'],
|
||||
visibility: ['responsive'],
|
||||
whitespace: ['responsive'],
|
||||
width: ['responsive'],
|
||||
zIndex: ['responsive']
|
||||
},
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Plugins https://tailwindcss.com/docs/plugins
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register any plugins you'd like to use in your
|
||||
| project. Tailwind's built-in `container` plugin is enabled by default to
|
||||
| give you a Bootstrap-style responsive container component out of the box.
|
||||
|
|
||||
| Be sure to view the complete plugin documentation to learn more about how
|
||||
| the plugin system works.
|
||||
|
|
||||
*/
|
||||
|
||||
plugins: [
|
||||
require('tailwindcss/plugins/container')({
|
||||
// center: true,
|
||||
// padding: '1rem',
|
||||
})
|
||||
],
|
||||
|
||||
/*
|
||||
|-----------------------------------------------------------------------------
|
||||
| Advanced Options https://tailwindcss.com/docs/configuration#options
|
||||
|-----------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can tweak advanced configuration options. We recommend
|
||||
| leaving these options alone unless you absolutely need to change them.
|
||||
|
|
||||
*/
|
||||
|
||||
options: {
|
||||
prefix: '',
|
||||
important: false,
|
||||
separator: ':'
|
||||
}
|
||||
};
|
||||
@@ -19,5 +19,7 @@ rules:
|
||||
mocha/no-pending-tests: error
|
||||
mocha/no-return-and-callback: warn
|
||||
mocha/no-skipped-tests: error
|
||||
mocha/no-setup-in-describe: off
|
||||
mocha/no-hooks-for-single-case: off
|
||||
|
||||
no-console: off # ¯\_(ツ)_/¯
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
const webpack = require('webpack');
|
||||
const middleware = require('webpack-dev-middleware');
|
||||
const express = require('express');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
const assets = require('../common/assets');
|
||||
const routes = require('../server/routes');
|
||||
const tests = require('./frontend/routes');
|
||||
@@ -18,8 +18,8 @@ module.exports = {
|
||||
app.use(wpm);
|
||||
assets.setMiddleware(wpm);
|
||||
expressWs(app, null, { perMessageDeflate: false });
|
||||
app.ws('/api/ws', require('../server/routes/ws'));
|
||||
routes(app);
|
||||
app.ws('/api/ws', require('../server/routes/ws'));
|
||||
tests(app);
|
||||
wpm.waitUntilValid(() => {
|
||||
server = app.listen(8000, resolve);
|
||||
|
||||
@@ -67,7 +67,7 @@ const serviceWorker = {
|
||||
},
|
||||
{
|
||||
// loads all assets from assets/ for use by common/assets.js
|
||||
test: require.resolve('./build/generate_asset_map.js'),
|
||||
test: require.resolve('./common/generate_asset_map.js'),
|
||||
use: ['babel-loader', 'val-loader']
|
||||
}
|
||||
]
|
||||
@@ -103,8 +103,7 @@ const web = {
|
||||
__dirname,
|
||||
'node_modules/@dannycoates/webcrypto-liner'
|
||||
),
|
||||
path.resolve(__dirname, 'node_modules/fluent'),
|
||||
path.resolve(__dirname, 'node_modules/fluent-intl-polyfill'),
|
||||
path.resolve(__dirname, 'node_modules/@fluent'),
|
||||
path.resolve(__dirname, 'node_modules/intl-pluralrules')
|
||||
],
|
||||
options: webJsOptions
|
||||
@@ -114,7 +113,8 @@ const web = {
|
||||
include: [path.resolve(__dirname, 'node_modules')],
|
||||
exclude: [
|
||||
path.resolve(__dirname, 'node_modules/crc'),
|
||||
path.resolve(__dirname, 'node_modules/fluent'),
|
||||
path.resolve(__dirname, 'node_modules/@fluent'),
|
||||
path.resolve(__dirname, 'node_modules/@sentry'),
|
||||
path.resolve(__dirname, 'node_modules/tslib'),
|
||||
path.resolve(__dirname, 'node_modules/webcrypto-core')
|
||||
],
|
||||
@@ -176,7 +176,7 @@ const web = {
|
||||
},
|
||||
{
|
||||
// loads all assets from assets/ for use by common/assets.js
|
||||
test: require.resolve('./build/generate_asset_map.js'),
|
||||
test: require.resolve('./common/generate_asset_map.js'),
|
||||
use: ['babel-loader', 'val-loader']
|
||||
}
|
||||
]
|
||||
@@ -216,6 +216,7 @@ const web = {
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const mode = argv.mode || 'production';
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`mode: ${mode}`);
|
||||
process.env.NODE_ENV = web.mode = serviceWorker.mode = mode;
|
||||
if (mode === 'development') {
|
||||
|
||||
Reference in New Issue
Block a user