Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Fiat Tux
Hat softwares
Lutim
Commits
1bf33e5d
Verified
Commit
1bf33e5d
authored
Apr 17, 2020
by
Luc Didry
Browse files
Merge branch 'development'
parents
442c2c35
72a5e2a5
Changes
32
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
1bf33e5d
...
...
@@ -174,3 +174,5 @@ cover:
script
:
-
make cover
coverage
:
'
/Total
.*\d+\.\d+$/'
except
:
-
tags
.weblate
0 → 100644
View file @
1bf33e5d
[weblate]
url = https://weblate.framasoft.org/api/
translation = lutim/development
CHANGELOG
View file @
1bf33e5d
Revision history for Lutim
0.1?.? ????-??-??
0.12.0 ????-??-??
- Add watermarking feature (#112)
0.11.6 2019-11-16
- Remove the "Support the author" dropdown
...
...
Makefile
View file @
1bf33e5d
EXTRACTDIR
=
-D
lib
-D
themes/default/templates
POT
=
themes/default/lib/Lutim/I18N/lutim.pot
ENPO
=
themes/default/lib/Lutim/I18N/en.po
XGETTEXT
=
carton
exec local
/bin/xgettext.pl
-u
CARTON
=
carton
exec
LUTIM
=
script/lutim
...
...
@@ -15,21 +16,10 @@ minify:
locales
:
$(XGETTEXT)
$(EXTRACTDIR)
-o
$(POT)
2>/dev/null
push-locales
:
ifeq
($(HEAD),$(filter $(HEAD),master development))
sed
-e
's@<project-version>.*</project-version>@<project-version>$(HEAD)</project-version>@'
-i
zanata.xml
&&
\
zanata-cli
-q
-B
push
endif
pull-locales
:
ifeq
($(HEAD),$(filter $(HEAD),master development))
sed
-e
's@<project-version>.*</project-version>@<project-version>$(HEAD)</project-version>@'
-i
zanata.xml
&&
\
zanata-cli
-q
-B
pull
endif
$(XGETTEXT)
$(EXTRACTDIR)
-o
$(ENPO)
2>/dev/null
stats-locales
:
zanata-cli
-q
stats
wlc
stats
podcheck
:
podchecker lib/Lutim/DB/Image.pm
...
...
lib/Lutim.pm
View file @
1bf33e5d
...
...
@@ -3,6 +3,7 @@ package Lutim;
use
Mojo::
Base
'
Mojolicious
';
use
Mojo::
IOLoop
;
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
vars
qw($im_loaded)
;
BEGIN
{
...
...
@@ -28,41 +29,32 @@ sub startup {
$self
->
plugin
('
DebugDumperHelper
');
my
$config
=
$self
->
plugin
('
Config
',
{
default
=>
{
provisioning
=>
100
,
provis_step
=>
5
,
length
=>
8
,
always_encrypt
=>
0
,
anti_flood_delay
=>
5
,
max_file_size
=>
10
*
1024
*
1024
,
https
=>
0
,
proposed_delays
=>
'
0,1,7,30,365
',
default_delay
=>
0
,
max_delay
=>
0
,
token_length
=>
24
,
crypto_key_length
=>
8
,
thumbnail_size
=>
100
,
theme
=>
'
default
',
dbtype
=>
'
sqlite
',
db_path
=>
'
lutim.db
',
max_files_in_zip
=>
15
,
prefix
=>
'
/
',
minion
=>
{
enabled
=>
0
,
dbtype
=>
'
sqlite
',
db_path
=>
'
minion.db
'
},
session_duration
=>
3600
,
cache_max_size
=>
0
,
memcached_servers
=>
[]
,
quiet_logs
=>
0
,
disable_img_stats
=>
0
,
x_frame_options
=>
'
DENY
',
x_content_type_options
=>
'
nosniff
',
x_xss_protection
=>
'
1; mode=block
',
}
default
=>
$default_config
});
if
(
$config
->
{
watermark_path
})
{
die
sprintf
('
%s does not exist or is not readable.
',
$config
->
{
watermark_path
})
unless
-
r
$config
->
{
watermark_path
};
my
$valid
=
{
center
=>
1
,
north
=>
1
,
northeast
=>
1
,
east
=>
1
,
southeast
=>
1
,
south
=>
1
,
southwest
=>
1
,
west
=>
1
,
northwest
=>
1
};
die
sprintf
('
%s is not a valid value for watermark_placement.
',
$config
->
{
watermark_placement
})
unless
$valid
->
{
lc
(
$config
->
{
watermark_placement
})};
$valid
=
{
'
tiling
'
=>
1
,
'
single
'
=>
1
,
'
none
'
=>
1
};
die
sprintf
('
%s is not a valid value for watermark_default.
',
$config
->
{
watermark_default
})
unless
$valid
->
{
lc
(
$config
->
{
watermark_default
})};
die
sprintf
('
%s is not a valid value for watermark_enforce.
',
$config
->
{
watermark_enforce
})
unless
$valid
->
{
lc
(
$config
->
{
watermark_enforce
})};
}
if
(
scalar
(
@
{
$config
->
{
memcached_servers
}}))
{
$self
->
plugin
(
CHI
=>
{
lutim_images_cache
=>
{
...
...
@@ -121,7 +113,7 @@ sub startup {
if
(
$config
->
{
minion
}
->
{
enabled
})
{
$self
->
config
->
{
minion
}
->
{
dbtype
}
=
'
sqlite
'
unless
defined
$config
->
{
minion
}
->
{
dbtype
};
if
(
$config
->
{
minion
}
->
{
dbtype
}
eq
'
sqlite
')
{
$
self
->
config
('
minion
')
->
{
db_path
}
=
'
minion.db
'
unless
defined
$config
->
{
minion
}
->
{
db_path
};
$config
->
{
minion
}
->
{
db_path
}
=
'
minion.db
'
unless
defined
$config
->
{
minion
}
->
{
db_path
};
$self
->
plugin
('
Minion
'
=>
{
SQLite
=>
'
sqlite:
'
.
$config
->
{
minion
}
->
{
db_path
}
});
}
elsif
(
$config
->
{
minion
}
->
{
dbtype
}
eq
'
postgresql
')
{
$self
->
plugin
('
PgURLHelper
');
...
...
@@ -178,14 +170,14 @@ sub startup {
});
# Authentication (if configured)
if
(
defined
(
$
self
->
config
('
ldap
')
)
||
defined
(
$
self
->
config
('
htpasswd
')
))
{
if
(
defined
(
$
self
->
config
('
ldap
')
))
{
if
(
defined
(
$config
->
{
ldap
}
)
||
defined
(
$config
->
{
htpasswd
}
))
{
if
(
defined
(
$config
->
{
ldap
}
))
{
require
Net::
LDAP
;
}
if
(
defined
(
$
self
->
config
('
htpasswd
')
))
{
if
(
defined
(
$config
->
{
htpasswd
}
))
{
require
Apache::
Htpasswd
;
}
die
'
Unable to read
'
.
$self
->
config
('
htpasswd
'
)
if
(
defined
(
$
self
->
config
('
htpasswd
')
)
&&
!-
r
$
self
->
config
('
htpasswd
')
);
die
sprintf
(
'
Unable to read
%s
',
$
config
->
{
htpasswd
}
)
if
(
defined
(
$config
->
{
htpasswd
}
)
&&
!-
r
$config
->
{
htpasswd
}
);
$self
->
plugin
('
Authentication
'
=>
{
autoload_user
=>
1
,
...
...
@@ -274,7 +266,7 @@ sub startup {
}
}
);
$self
->
app
->
sessions
->
default_expiration
(
$
self
->
config
('
session_duration
')
);
$self
->
app
->
sessions
->
default_expiration
(
$config
->
{
session_duration
}
);
}
$self
->
defaults
(
layout
=>
'
default
');
...
...
@@ -287,7 +279,7 @@ sub startup {
$r
->
add_condition
(
authorized
=>
sub
{
my
(
$r
,
$c
,
$captures
)
=
@_
;
return
1
unless
(
defined
(
$
self
->
config
('
ldap
')
)
||
defined
(
$
self
->
config
('
htpasswd
')
));
return
1
unless
(
defined
(
$config
->
{
ldap
}
)
||
defined
(
$config
->
{
htpasswd
}
));
return
$c
->
is_user_authenticated
;
});
...
...
@@ -306,7 +298,7 @@ sub startup {
to
('
Authent#index
');
if
(
defined
$
self
->
config
('
ldap
')
||
defined
$
self
->
config
('
htpasswd
')
)
{
if
(
defined
$config
->
{
ldap
}
||
defined
$config
->
{
htpasswd
}
)
{
# Login page
$r
->
get
('
/login
')
->
to
('
Authent#index
')
...
...
lib/Lutim/Command/cron/cleanbdd.pm
View file @
1bf33e5d
...
...
@@ -3,6 +3,7 @@ package Lutim::Command::cron::cleanbdd;
use
Mojo::
Base
'
Mojolicious::Command
';
use
Mojo::
File
;
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
FindBin
qw($Bin)
;
use
File::
Spec
qw(catfile)
;
...
...
@@ -21,10 +22,7 @@ sub run {
}
my
$config
=
$c
->
app
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
{
keep_ip_during
=>
365
,
dbtype
=>
'
sqlite
',
}
default
=>
$default_config
});
my
$separation
=
time
()
-
$config
->
{
keep_ip_during
}
*
86400
;
...
...
lib/Lutim/Command/cron/cleanfiles.pm
View file @
1bf33e5d
...
...
@@ -3,6 +3,7 @@ package Lutim::Command::cron::cleanfiles;
use
Mojo::
Base
'
Mojolicious::Command
';
use
Mojo::
File
;
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
Lutim
;
use
FindBin
qw($Bin)
;
use
File::
Spec
qw(catfile)
;
...
...
@@ -22,9 +23,7 @@ sub run {
}
my
$config
=
$c
->
app
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
{
dbtype
=>
'
sqlite
',
}
default
=>
$default_config
});
my
$l
=
Lutim
->
new
;
...
...
lib/Lutim/Command/cron/stats.pm
View file @
1bf33e5d
...
...
@@ -6,6 +6,7 @@ use Mojo::Util qw(encode);
use
Mojo::
File
;
use
Mojo::
JSON
qw(encode_json)
;
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
DateTime
;
use
FindBin
qw($Bin)
;
use
File::
Spec
qw(catfile)
;
...
...
@@ -26,11 +27,7 @@ sub run {
}
my
$config
=
$c
->
app
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
{
theme
=>
'
default
',
stats_day_num
=>
365
,
dbtype
=>
'
sqlite
'
}
default
=>
$default_config
});
my
$template
=
'
themes/
'
.
$config
->
{
theme
}
.
'
/templates/data.html.ep.template
';
...
...
lib/Lutim/Command/cron/watch.pm
View file @
1bf33e5d
...
...
@@ -3,6 +3,7 @@ package Lutim::Command::cron::watch;
use
Mojo::
Base
'
Mojolicious::Command
';
use
Filesys::
DiskUsage
qw/du/
;
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
Lutim
;
use
Mojo::
File
;
use
Switch
;
...
...
@@ -24,10 +25,7 @@ sub run {
}
my
$config
=
$c
->
app
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
{
policy_when_full
=>
'
warn
',
dbtype
=>
'
sqlite
',
}
default
=>
$default_config
});
if
(
defined
(
$config
->
{
max_total_size
}))
{
...
...
lib/Lutim/Command/image.pm
View file @
1bf33e5d
...
...
@@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious::Command';
use
Mojo::
Util
qw(getopt)
;
use
Mojo::
Collection
'
c
';
use
Lutim::DB::
Image
;
use
Lutim::
DefaultConfig
qw($default_config)
;
use
FindBin
qw($Bin)
;
use
File::
Spec
qw(catfile)
;
...
...
@@ -25,38 +26,7 @@ sub run {
}
my
$config
=
$c
->
app
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
{
provisioning
=>
100
,
provis_step
=>
5
,
length
=>
8
,
always_encrypt
=>
0
,
anti_flood_delay
=>
5
,
max_file_size
=>
10
*
1024
*
1024
,
https
=>
0
,
proposed_delays
=>
'
0,1,7,30,365
',
default_delay
=>
0
,
max_delay
=>
0
,
token_length
=>
24
,
crypto_key_length
=>
8
,
thumbnail_size
=>
100
,
theme
=>
'
default
',
dbtype
=>
'
sqlite
',
db_path
=>
'
lutim.db
',
max_files_in_zip
=>
15
,
prefix
=>
'
/
',
minion
=>
{
enabled
=>
0
,
dbtype
=>
'
sqlite
',
db_path
=>
'
minion.db
'
},
cache_max_size
=>
0
,
memcached_servers
=>
[]
,
quiet_logs
=>
0
,
disable_img_stats
=>
0
,
x_frame_options
=>
'
DENY
',
x_content_type_options
=>
'
nosniff
',
x_xss_protection
=>
'
1; mode=block
',
}
default
=>
$default_config
});
if
(
scalar
(
@
{
$config
->
{
memcached_servers
}}))
{
...
...
lib/Lutim/Controller/Image.pm
View file @
1bf33e5d
...
...
@@ -285,6 +285,7 @@ sub add {
my
$upload
=
$c
->
param
('
file
');
my
$file_url
=
$c
->
param
('
lutim-file-url
');
my
$keep_exif
=
$c
->
param
('
keep-exif
');
my
$wm
=
$c
->
param
('
watermark
');
if
(
!
defined
(
$c
->
stash
('
stop_upload
')))
{
if
(
defined
(
$file_url
)
&&
$file_url
)
{
...
...
@@ -406,14 +407,56 @@ sub add {
# Automatic rotation from EXIF tag
$im
->
AutoOrient
();
# Update the uploaded file with it's auto-rotated clone
# Get dimensions
$width
=
$im
->
Get
('
width
');
$height
=
$im
->
Get
('
height
');
# Optionally add watermark
if
(
$c
->
config
('
watermark_path
')
&&
(
(
$wm
&&
$wm
ne
'
none
')
||
$c
->
config
('
watermark_enforce
')
ne
'
none
'
))
{
my
$watermarkim
=
Image::
Magick
->
new
;
$watermarkim
->
ReadImage
(
$c
->
config
('
watermark_path
'));
$watermarkim
->
Evaluate
(
operator
=>
'
Multiply
',
value
=>
0.25
,
channel
=>
'
Alpha
'
);
if
(
$height
<=
80
)
{
$watermarkim
->
Resize
(
geometry
=>
'
x10
');
}
else
{
$watermarkim
->
Resize
(
geometry
=>
'
x80
');
}
# Add one watermark or repeat it all over the image?
my
$tilingw
=
1
if
(
$c
->
config
('
watermark_enforce
')
eq
'
tiling
'
||
$wm
eq
'
tiling
');
my
$singlew
=
1
if
(
$c
->
config
('
watermark_enforce
')
eq
'
single
'
||
$wm
eq
'
single
');
if
(
$tilingw
)
{
$im
->
Composite
(
image
=>
$watermarkim
,
compose
=>
'
Dissolve
',
tile
=>
'
True
',
gravity
=>
'
Center
'
);
}
elsif
(
$singlew
)
{
$im
->
Composite
(
image
=>
$watermarkim
,
compose
=>
'
Dissolve
',
tile
=>
'
False
',
x
=>
'
20
',
y => '20',
gravity => $c->config('watermark_placement')
);
}
}
# Update the uploaded file with it's auto-rotated/watermarked clone
my $asset =
Mojo::Asset::
Memory
->
new
->
add_chunk
(
$im
->
ImageToBlob
());
$upload
->
asset
(
$asset
);
# Create the thumbnail
$width
=
$im
->
Get
('
width
');
$height
=
$im
->
Get
('
height
');
$im
->
Resize
(
geometry
=>
'
x85
');
$im
->
Resize
(
geometry
=>
'
x85
');
$thumb
=
'
data:
'
.
$mediatype
.
'
;base64,
';
if
(
$mediatype
eq
'
image/gif
')
{
...
...
lib/Lutim/DefaultConfig.pm
0 → 100644
View file @
1bf33e5d
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package
Lutim::
DefaultConfig
;
require
Exporter
;
@ISA
=
qw(Exporter)
;
@EXPORT_OK
=
qw($default_config)
;
our
$default_config
=
{
provisioning
=>
100
,
provis_step
=>
5
,
length
=>
8
,
always_encrypt
=>
0
,
anti_flood_delay
=>
5
,
max_file_size
=>
10
*
1024
*
1024
,
https
=>
0
,
proposed_delays
=>
'
0,1,7,30,365
',
default_delay
=>
0
,
max_delay
=>
0
,
token_length
=>
24
,
crypto_key_length
=>
8
,
thumbnail_size
=>
100
,
watermark_path
=>
'',
watermark_placement
=>
'
SouthEast
',
watermark_default
=>
'
none
',
watermark_enforce
=>
'
none
',
theme
=>
'
default
',
dbtype
=>
'
sqlite
',
db_path
=>
'
lutim.db
',
max_files_in_zip
=>
15
,
prefix
=>
'
/
',
minion
=>
{
enabled
=>
0
,
dbtype
=>
'
sqlite
',
db_path
=>
'
minion.db
'
},
session_duration
=>
3600
,
cache_max_size
=>
0
,
memcached_servers
=>
[]
,
quiet_logs
=>
0
,
disable_img_stats
=>
0
,
x_frame_options
=>
'
DENY
',
x_content_type_options
=>
'
nosniff
',
x_xss_protection
=>
'
1; mode=block
',
stats_day_num
=>
365
,
keep_ip_during
=>
365
,
policy_when_full
=>
'
warn
',
};
1
;
lib/Lutim/Plugin/Helpers.pm
View file @
1bf33e5d
...
...
@@ -47,6 +47,7 @@ sub register {
$app
->
helper
(
max_delay
=>
\
&_max_delay
);
$app
->
helper
(
default_delay
=>
\
&_default_delay
);
$app
->
helper
(
is_selected
=>
\
&_is_selected
);
$app
->
helper
(
is_wm_selected
=>
\
&_is_wm_selected
);
$app
->
helper
(
crypt
=>
\
&_crypt
);
$app
->
helper
(
decrypt
=>
\
&_decrypt
);
$app
->
helper
(
delete_image
=>
\
&_delete_image
);
...
...
@@ -250,6 +251,13 @@ sub _is_selected {
return
(
$num
==
$c
->
default_delay
)
?
'
selected="selected"
'
:
'';
}
sub
_is_wm_selected
{
my
$c
=
shift
;
my
$wm
=
shift
;
return
(
$wm
eq
$c
->
config
('
watermark_default
'))
?
'
selected="selected"
'
:
'';
}
sub
_crypt
{
my
$c
=
shift
;
my
$upload
=
shift
;
...
...
lib/Mounter.pm
View file @
1bf33e5d
...
...
@@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious';
use
Mojo::
File
;
use
FindBin
qw($Bin)
;
use
File::
Spec
qw(catfile)
;
use
Lutim::
DefaultConfig
qw($default_config)
;
# This method will run once at server start
sub
startup
{
...
...
@@ -18,43 +19,10 @@ sub startup {
$cfile
=
Mojo::
File
->
new
(
$Bin
,
'
..
',
$ENV
{
MOJO_CONFIG
});
}
}
my
$config
=
$self
->
plugin
('
Config
'
=>
{
file
=>
$cfile
,
default
=>
{
provisioning
=>
100
,
provis_step
=>
5
,
length
=>
8
,
always_encrypt
=>
0
,
anti_flood_delay
=>
5
,
max_file_size
=>
10
*
1024
*
1024
,
https
=>
0
,
proposed_delays
=>
'
0,1,7,30,365
',
default_delay
=>
0
,
max_delay
=>
0
,
token_length
=>
24
,
crypto_key_length
=>
8
,
thumbnail_size
=>
100
,
theme
=>
'
default
',
dbtype
=>
'
sqlite
',
db_path
=>
'
lutim.db
',
max_files_in_zip
=>
15
,
prefix
=>
'
/
',
minion
=>
{
enabled
=>
0
,
dbtype
=>
'
sqlite
',
db_path
=>
'
minion.db
'
},
cache_max_size
=>
0
,
memcached_servers
=>
[]
,
quiet_logs
=>
0
,
disable_img_stats
=>
0
,
x_frame_options
=>
'
DENY
',
x_content_type_options
=>
'
nosniff
',
x_xss_protection
=>
'
1; mode=block
',
}
}
);
my
$config
=
$self
->
plugin
('
Config
',
{
file
=>
$cfile
,
default
=>
$default_config
});
$config
->
{
prefix
}
=
$config
->
{
url_sub_dir
}
if
(
defined
(
$config
->
{
url_sub_dir
})
&&
$config
->
{
prefix
}
eq
'
/
');
...
...
lutim.conf.template
View file @
1bf33e5d
...
...
@@ -102,6 +102,29 @@
# optional, default is 0
#always_encrypt => 0,
# you can allow to use a watermark on the uploaded images (or enforce its use)
# define a path to the watermark image (provide an image with alpha channel)
# you can define the path relative to lutim directory or set an absolute path
# to disable the usage of a watermark, leave it blank or commented
# optional, no default
#watermark_path => '',
# the watermark can be a tiling one or a single one
# when using a small one, you can choose where to place it
# valid values are 'Center', 'North', 'NorthEast', 'East', 'SouthEast', 'South', 'SouthWest', 'West' and 'NorthWest' (case insensitive)
# optional, default is 'SouthEast'
#watermark_placement => 'SouthEast',
# choose which watermark (tiling, single or none) should be used by default
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_default => 'none',
# choose which watermark (tiling, single or none) should be enforced (users will always have a watermark and won’t be able to disable it)
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_enforce => 'none',
# length of the image's delete token
# optional, default is 24
#token_length => 24,
...
...
themes/default/lib/Lutim/I18N/ar.po
View file @
1bf33e5d
...
...
@@ -10,17 +10,17 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 20
19-11-16 09:11
+0000\n"
"Last-Translator:
ButterflyOfFire <butterflyoffire@protonmail.com
>\n"
"PO-Revision-Date: 20
20-03-09 16:23
+0000\n"
"Last-Translator:
Luc Didry <luc@framasoft.org
>\n"
"Language-Team: Arabic <https://weblate.framasoft.org/projects/lutim/"
"de
velopment
/ar/>\n"
"de
fault-theme
/ar/>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 3.
9.1
\n"
"X-Generator: Weblate 3.
11.2
\n"
"n%100<=10 ? 3: n%100>=11 ? 4 : 5);\n"
#. (7)
...
...
@@ -110,7 +110,7 @@ msgstr ""
#: themes/default/templates/stats.html.ep:15
msgid "Delay repartition chart for enabled images"
msgstr ""
msgstr "
المنحنى البياني للتوزيع الزمني للصور النشطة
"
#: themes/default/templates/index.html.ep:133 themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:196 themes/default/templates/myfiles.html.ep:124 themes/default/templates/myfiles.html.ep:45 themes/default/templates/partial/lutim.js.ep:161
msgid "Delete at first view?"
...
...
@@ -152,8 +152,8 @@ msgid ""
"to delete the image when you want."
msgstr ""
"إسحب ثم القي صورة ما على المساحة المخصصة لذلك أو قم باستخدام الأسلوب المعتاد "
"لإرسال الملفات
و سيقوم لوتان بعدها بتوفير أربع روابط. رابط لعرض الصورة و "
"
آخر
لتنزيل الصورة مباشرة و آخر يمكنكم إستخدامه على شبكات التواصل الإجتماعي و "
"لإرسال الملفات و سيقوم لوتان بعدها بتوفير أربع روابط. رابط لعرض الصورة و
آخر
"
"لتنزيل الصورة مباشرة و آخر يمكنكم إستخدامه على شبكات التواصل الإجتماعي و "
"أخيرا رابط آخر يمكّنكم من حذف الصورة إن شئتم."
#: themes/default/templates/index.html.ep:168 themes/default/templates/index.html.ep:199
...
...
@@ -174,7 +174,7 @@ msgstr "تنتهي مدة صلاحيتها في"
#: themes/default/templates/myfiles.html.ep:112
msgid "Export localStorage data"
msgstr ""
msgstr "
تصدير بيانات localStorage
"
#: themes/default/templates/myfiles.html.ep:121
msgid "File name"
...
...
@@ -242,7 +242,7 @@ msgstr "الصورة غير موجودة."
#: themes/default/templates/myfiles.html.ep:113
msgid "Import localStorage data"
msgstr ""
msgstr "
استيراد بيانات localStorage
"
#: themes/default/templates/partial/navbar.html.ep:69
msgid "Informations"
...
...
@@ -314,6 +314,8 @@ msgid ""
"also the name of the free (as in free speech) software which provides this "
"service."
msgstr ""
"لوتيم أو Lutim خدمة مجانية ومجهولة لاستضافة الصور. ويعني كذلك اسم البرنامج "
"الحر الموفّر لهذه الخدمة."
#: themes/default/templates/about.html.ep:25
msgid "Main developers"
...
...
@@ -321,7 +323,7 @@ msgstr "المطورون الرئيسيون"
#: themes/default/templates/index.html.ep:91 themes/default/templates/index.html.ep:93 themes/default/templates/partial/lutim.js.ep:86 themes/default/templates/partial/lutim.js.ep:89
msgid "Markdown syntax"
msgstr ""
msgstr "
صيغة ماركداون
"
#: themes/default/templates/partial/myfiles.js.ep:149
msgid "Modify expiration delay"
...
...
@@ -333,7 +335,7 @@ msgstr "صوري"
#: themes/default/templates/gallery.html.ep:45
msgid "Next (arrow right)"
msgstr ""
msgstr "
التالي (السهم إلى اليمين)
"