Translation on Firefox Translations models; new logo
- Email translation moves from LibreTranslate to our own translator
service (translator/): Mozilla's Firefox Translations models on the
Bergamot engine, fastText language detection (176 languages). Polish,
English, German, French, Spanish and Italian on first start (~350 MB
instead of ~10 GB); Admin panel > Email translation installs and
removes languages. Built and pushed as the `translator` image.
- Every message is translated paragraph by paragraph as plain text;
names travel with their sentence and are kept only where the model
changed them; a sentence start the model copied ("Enclosed") is tried
again in lower case; list markers are not sent
- The Translate button shows only for installed languages
- New logo: favicon, app/maskable/iPhone icons, notification badge,
email logo and calendar copy regenerated; BIMI logo rebuilt in SVG
Tiny PS with its gradients; masks render in browsers
- Launch screen background is the app's dark grey
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -8,9 +8,31 @@
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="ultimo-logo-signet.svg"
|
||||
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="2.5488772"
|
||||
inkscape:cx="89.451151"
|
||||
inkscape:cy="-10.20057"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1403"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" /><defs
|
||||
id="defs1"><linearGradient
|
||||
id="linearGradient11"><stop
|
||||
style="stop-color:#f89629;stop-opacity:1;"
|
||||
@@ -26,9 +48,97 @@
|
||||
x2="54.340946"
|
||||
y2="162.66415"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /></defs><g
|
||||
id="layer1"
|
||||
transform="translate(-21.70051,-187.41349)"><path
|
||||
id="path1-2"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:url(#linearGradient12);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||
d="m 58.875622,191.58757 c -2.152336,-7.4e-4 -4.067804,1.84724 -4.067104,4.1266 v 2.85212 c -0.073,-0.005 -0.146556,-0.007 -0.220195,-0.007 H 44.088203 33.589648 c -0.04176,-7e-5 -0.0835,5.9e-4 -0.125155,0.002 v -2.78918 c -1.66e-4,-2.27807 -1.959264,-4.12477 -4.110377,-4.12494 -2.151113,1.8e-4 -4.208743,1.84687 -4.208908,4.12494 v 15.55127 c -3.9e-5,0.005 -0.02954,3.84339 2.173004,7.60498 2.20396,3.76402 7.038201,7.38257 14.452668,7.38257 h 4.580673 c 7.417703,0 12.26918,-3.66617 14.505859,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.0016,-0.0344 V 195.7141 c 7e-4,-2.27872 -2.102019,-4.12642 -4.253744,-4.1266 z m -2.007917,7.94794 v 11.57584 0.0286 c 0,0 -0.06644,2.0824 -1.311391,4.18416 -0.572022,0.96572 -1.445415,2.15762 -2.917676,2.99793 -1.472263,0.8403 -3.460652,1.33079 -6.272222,1.33079 H 41.78535 c -2.82381,0 -4.798635,-0.47938 -6.256969,-1.30429 -1.458334,-0.8249 -2.313565,-2.00343 -2.85901,-2.93496 -1.196636,-2.04365 -1.230039,-4.07193 -1.230039,-4.07193 l -0.0011,-0.0141 v -0.0157 -11.69637 l 0.02191,0.0178 7.82e-4,10e-4 c 0.03515,0.0487 0.07994,0.0958 0.133761,0.14041 l 5.513859,4.57144 5.515036,4.57144 c 0.651946,0.53945 2.279028,0.53945 2.930974,0 l 5.515034,-4.57144 5.514252,-4.57144 c 0.01986,-0.0164 0.03852,-0.0331 0.05593,-0.0501 l 7.82e-4,-8.2e-4 z" /></g></svg>
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="-1000"
|
||||
y="-1000"
|
||||
width="3000"
|
||||
height="3000"
|
||||
id="mask1788"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1788"
|
||||
sodipodi:nodetypes="cccsccc" /></mask><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1769"
|
||||
id="linearGradient1789"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="37.71608"
|
||||
y1="123.22854"
|
||||
x2="27.709011"
|
||||
y2="135.24788" /><linearGradient
|
||||
id="linearGradient1769"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#ffe3ac;stop-opacity:0.36078355;"
|
||||
offset="0.00003701"
|
||||
id="stop1769" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop1770" /></linearGradient><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="-1000"
|
||||
y="-1000"
|
||||
width="3000"
|
||||
height="3000"
|
||||
id="mask1776-6"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1776-1"
|
||||
sodipodi:nodetypes="cccsccc" /></mask><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient11"
|
||||
id="linearGradient13-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,-18.692802,-93.278335)"
|
||||
x1="54.340946"
|
||||
y1="122.84999"
|
||||
x2="54.340946"
|
||||
y2="162.66415" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8"
|
||||
id="radialGradient816"
|
||||
cx="8.0343275"
|
||||
cy="13.452971"
|
||||
fx="8.0343275"
|
||||
fy="13.452971"
|
||||
r="16.678839"
|
||||
gradientTransform="matrix(-0.29271702,0.00410386,-0.01334442,-0.95181978,11.840139,23.950941)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient8"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#fa7367;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8" /><stop
|
||||
style="stop-color:#fa7367;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop9" /></linearGradient><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6"
|
||||
id="radialGradient815"
|
||||
cx="35.709007"
|
||||
cy="12.042645"
|
||||
fx="35.709007"
|
||||
fy="12.042645"
|
||||
r="16.740065"
|
||||
gradientTransform="matrix(0.25712152,0.00260463,-0.00969379,0.95694375,26.644192,0.97301292)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient6"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#fab23b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6" /><stop
|
||||
style="stop-color:#fab23a;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7" /></linearGradient></defs><g
|
||||
id="g816"
|
||||
transform="translate(0.128676,-0.079965)"><path
|
||||
id="path1-2-1-1"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#linearGradient13-6);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="m 37.175189,4.174075 c -2.15234,-7.4e-4 -4.0678,1.84724 -4.0671,4.1266 v 2.85212 c -0.073,-0.005 -0.14656,-0.007 -0.2202,-0.007 h -10.50012 -10.49855 c -0.0418,-7e-5 -0.0835,5.9e-4 -0.12516,0.002 v -2.78918 c -1.6e-4,-2.27807 -1.9592601,-4.12477 -4.1103801,-4.12494 -2.15111,1.8e-4 -4.20874,1.84687 -4.2089,4.12494 v 15.55127 c -4e-5,0.005 -0.0295,3.84339 2.173,7.60498 2.20396,3.76402 7.0382001,7.38257 14.4526701,7.38257 h 4.58067 c 7.4177,0 12.26918,-3.66617 14.50586,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.002,-0.0344 V 8.300605 c 7e-4,-2.27872 -2.10202,-4.12642 -4.25374,-4.1266 z m -2.00792,7.9252 v 11.59858 0.0286 c 0,0 -0.0664,2.0824 -1.31139,4.18416 -0.57202,0.96572 -1.44541,2.15762 -2.91767,2.99793 -1.47227,0.8403 -3.46066,1.33079 -6.27223,1.33079 h -4.58106 c -2.82381,0 -4.79864,-0.47938 -6.25697,-1.30429 -1.45833,-0.8249 -2.31357,-2.00343 -2.85901,-2.93496 -1.1966401,-2.04365 -1.2300401,-4.07193 -1.2300401,-4.07193 l -0.001,-0.0141 v -0.0157 -11.69637 l 1.96e-4,-0.0142 0.0035,-0.008 c 0.05128,0.0487 0.18806,0.16304 0.24192,0.20765 l 5.4247011,4.54513 5.51504,4.57144 c 0.65194,0.53945 2.27903,0.53945 2.93097,0 l 5.51504,-4.57144 5.487378,-4.57351 c 0.0199,-0.0164 0.04083,-0.0331 0.06003,-0.048 l 0.02765,-0.0215 z"
|
||||
sodipodi:nodetypes="cccccccccccssssccccccccssssssccccccccccccscc" /><path
|
||||
id="path1-2-1-9"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient816);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="M 3.6452555,7.14375 C 3.5159759,7.5278714 3.4447807,7.9357538 3.444751,8.3586629 V 23.909652 c -4e-5,0.005 -0.029506,3.84363 2.172994,7.60522 2.20396,3.76402 7.038395,7.382495 14.452865,7.382495 h 4.580598 c 5.433936,0 9.490679,-1.96731 12.151197,-4.504117 -1.517177,-1.218257 -3.218664,-2.595334 -5.013648,-4.05505 -0.258984,0.201994 -0.541601,0.394146 -0.850594,0.570508 -1.47227,0.8403 -3.460398,1.330668 -6.271968,1.330668 h -4.581116 c -2.82381,0 -4.798652,-0.479403 -6.256982,-1.304313 -1.45833,-0.8249 -2.313817,-2.003692 -2.859257,-2.935222 -1.1966406,-2.04365 -1.2298996,-4.071586 -1.2298996,-4.071586 l -0.00103,-0.01395 v -0.01602 -11.696444 -0.01395 l 0.00362,-0.0083 c 0.05128,0.0487 0.1879857,0.16313 0.2418457,0.20774 l 5.4249919,4.545459 5.514909,4.571297 c 0.0844,0.06984 0.185312,0.130661 0.298173,0.182418 C 16.15064,17.512631 11.679239,13.804108 9.750826,12.186336 7.4531167,10.290397 5.3700283,8.5696704 3.6452555,7.14375 Z" /><path
|
||||
id="path1-2-1-7"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient815);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="m 41.226941,7.09104 c -1.718284,1.4205409 -3.7895,3.131915 -6.072498,5.015715 -1.93499,1.62329 -6.430112,5.351263 -11.522294,9.54257 0.08232,-0.04302 0.156783,-0.0915 0.221692,-0.145211 l 5.514909,-4.571297 5.48752,-4.573881 c 0.0199,-0.0164 0.04075,-0.03316 0.05994,-0.04806 l 0.0279,-0.02119 0.222726,-0.190169 v 11.598258 0.02894 c 0,0 -0.06656,2.081964 -1.311548,4.183724 -0.57202,0.96572 -1.445392,2.157957 -2.917652,2.998267 -1.47227,0.8403 -3.460398,1.330668 -6.271968,1.330668 h -4.581116 c -2.82381,0 -4.798652,-0.479403 -6.256982,-1.304313 -0.308682,-0.174605 -0.590588,-0.364744 -0.848011,-0.565341 -1.805553,1.467965 -3.513225,2.849693 -5.0307002,4.067452 2.6425302,2.518552 6.6894502,4.460193 12.1212242,4.460193 h 4.580599 c 7.4177,0 12.269411,-3.665883 14.506091,-7.441923 2.23668,-3.77604 2.270146,-7.635193 2.270146,-7.635193 l 0.0021,-0.03411 V 8.3007853 C 41.429125,7.8798785 41.357396,7.4736084 41.226941,7.09104 Z" /></g></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -8,10 +8,48 @@
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="ultimo-logo.svg"
|
||||
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.9327415"
|
||||
inkscape:cx="187.29872"
|
||||
inkscape:cy="135.81744"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" /><defs
|
||||
id="defs1"><linearGradient
|
||||
id="linearGradient8"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#fa7367;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8" /><stop
|
||||
style="stop-color:#fa7367;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop9" /></linearGradient><linearGradient
|
||||
id="linearGradient6"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#fab23b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6" /><stop
|
||||
style="stop-color:#fab23a;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7" /></linearGradient><linearGradient
|
||||
id="linearGradient11"><stop
|
||||
style="stop-color:#f89629;stop-opacity:1;"
|
||||
offset="0.20198774"
|
||||
@@ -26,13 +64,82 @@
|
||||
x2="54.340946"
|
||||
y2="162.66415"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /></defs><g
|
||||
id="layer1"
|
||||
transform="translate(-21.70051,-187.41349)"><path
|
||||
id="path1-2"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:url(#linearGradient12);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||
d="m 58.875622,191.58757 c -2.152336,-7.4e-4 -4.067804,1.84724 -4.067104,4.1266 v 2.85212 c -0.073,-0.005 -0.146556,-0.007 -0.220195,-0.007 H 44.088203 33.589648 c -0.04176,-7e-5 -0.0835,5.9e-4 -0.125155,0.002 v -2.78918 c -1.66e-4,-2.27807 -1.959264,-4.12477 -4.110377,-4.12494 -2.151113,1.8e-4 -4.208743,1.84687 -4.208908,4.12494 v 15.55127 c -3.9e-5,0.005 -0.02954,3.84339 2.173004,7.60498 2.20396,3.76402 7.038201,7.38257 14.452668,7.38257 h 4.580673 c 7.417703,0 12.26918,-3.66617 14.505859,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.0016,-0.0344 V 195.7141 c 7e-4,-2.27872 -2.102019,-4.12642 -4.253744,-4.1266 z m -2.007917,7.94794 v 11.57584 0.0286 c 0,0 -0.06644,2.0824 -1.311391,4.18416 -0.572022,0.96572 -1.445415,2.15762 -2.917676,2.99793 -1.472263,0.8403 -3.460652,1.33079 -6.272222,1.33079 H 41.78535 c -2.82381,0 -4.798635,-0.47938 -6.256969,-1.30429 -1.458334,-0.8249 -2.313565,-2.00343 -2.85901,-2.93496 -1.196636,-2.04365 -1.230039,-4.07193 -1.230039,-4.07193 l -0.0011,-0.0141 v -0.0157 -11.69637 l 0.02191,0.0178 7.82e-4,10e-4 c 0.03515,0.0487 0.07994,0.0958 0.133761,0.14041 l 5.513859,4.57144 5.515036,4.57144 c 0.651946,0.53945 2.279028,0.53945 2.930974,0 l 5.515034,-4.57144 5.514252,-4.57144 c 0.01986,-0.0164 0.03852,-0.0331 0.05593,-0.0501 l 7.82e-4,-8.2e-4 z" /><path
|
||||
style="font-weight:bold;font-size:44.7887px;line-height:1.5;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';letter-spacing:0.223944px;fill:#f74e6a;stroke-width:56.4265;stroke-linecap:round"
|
||||
d="m 73.758258,226.15765 q -1.70197,0 -3.09042,-0.85098 -1.38845,-0.85099 -2.239435,-2.23944 -0.850985,-1.38845 -0.850985,-3.09042 v -28.35124 h 5.912108 v 28.1273 q 0,0.22394 0.134366,0.4031 0.179155,0.13436 0.403099,0.13436 h 4.971545 v 5.86732 z m 14.869774,0 q -1.701971,0 -3.090421,-0.85098 -1.388449,-0.85099 -2.239435,-2.23944 -0.850985,-1.38845 -0.850985,-3.09042 v -27.76899 h 5.86732 v 7.97239 h 10.122246 v 5.86732 H 88.314511 v 13.70534 q 0,0.22394 0.134366,0.4031 0.179155,0.13436 0.403098,0.13436 h 9.584782 v 5.86732 z m 13.705278,0 v 0 -25.97744 h 5.86732 v 25.97744 z m 0,-28.57519 v 0 -5.91211 h 5.86732 v 5.91211 z m 10.25654,28.57519 v 0 -25.97744 h 32.20307 q 1.74676,0 3.13521,0.85098 1.38845,0.85099 2.19465,2.23944 0.85098,1.38845 0.85098,3.09042 v 19.7966 h -5.82253 v -19.57266 q 0,-0.22394 -0.17915,-0.35831 -0.17916,-0.17915 -0.4031,-0.17915 h -9.27126 q -0.22395,0 -0.4031,0.17915 -0.13437,0.13437 -0.13437,0.35831 v 19.57266 h -5.91211 v -19.57266 q 0,-0.22394 -0.17915,-0.35831 -0.13437,-0.17915 -0.35831,-0.17915 h -9.31605 q -0.22394,0 -0.4031,0.17915 -0.13436,0.13437 -0.13436,0.35831 v 19.57266 z m 50.07371,0 q -1.70197,0 -3.09042,-0.85098 -1.38845,-0.85099 -2.23944,-2.23944 -0.85098,-1.38845 -0.85098,-3.09042 v -13.61576 q 0,-1.70197 0.85098,-3.09042 0.85099,-1.38845 2.23944,-2.23944 1.38845,-0.85098 3.09042,-0.85098 h 14.01886 q 1.70197,0 3.09042,0.85098 1.43324,0.85099 2.23944,2.23944 0.85098,1.38845 0.85098,3.09042 v 13.61576 q 0,1.70197 -0.85098,3.09042 -0.8062,1.38845 -2.19465,2.23944 -1.38845,0.85098 -3.13521,0.85098 z m 0.22394,-5.86732 h 13.57098 q 0.22394,0 0.35831,-0.13436 0.17915,-0.17916 0.17915,-0.4031 v -13.16788 q 0,-0.22394 -0.17915,-0.35831 -0.13437,-0.17915 -0.35831,-0.17915 H 162.8875 q -0.22394,0 -0.4031,0.17915 -0.13436,0.13437 -0.13436,0.35831 v 13.16788 q 0,0.22394 0.13436,0.4031 0.17916,0.13436 0.4031,0.13436 z"
|
||||
id="text13"
|
||||
aria-label="ltimo" /></g></svg>
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient11"
|
||||
id="linearGradient13"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,-18.692802,-93.278335)"
|
||||
x1="54.340946"
|
||||
y1="122.84999"
|
||||
x2="54.340946"
|
||||
y2="162.66415" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1769"
|
||||
id="linearGradient1789"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="37.71608"
|
||||
y1="123.22854"
|
||||
x2="27.709011"
|
||||
y2="135.24788" /><linearGradient
|
||||
id="linearGradient1769"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#ffe3ac;stop-opacity:0.36078355;"
|
||||
offset="0.00003701"
|
||||
id="stop1769" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop1770" /></linearGradient><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask1788-1"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1788-2"
|
||||
sodipodi:nodetypes="cccsccc" /></mask><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask1776-6-6"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1776-1-2"
|
||||
sodipodi:nodetypes="cccsccc" /></mask><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6"
|
||||
id="radialGradient815"
|
||||
cx="35.709007"
|
||||
cy="12.042645"
|
||||
fx="35.709007"
|
||||
fy="12.042645"
|
||||
r="16.740065"
|
||||
gradientTransform="matrix(0.25712152,0.00260463,-0.00969379,0.95694375,26.644192,0.97301292)"
|
||||
gradientUnits="userSpaceOnUse" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8"
|
||||
id="radialGradient816"
|
||||
cx="8.0343275"
|
||||
cy="13.452971"
|
||||
fx="8.0343275"
|
||||
fy="13.452971"
|
||||
r="16.678839"
|
||||
gradientTransform="matrix(-0.29271702,0.00410386,-0.01334442,-0.95181978,11.840139,23.950941)"
|
||||
gradientUnits="userSpaceOnUse" /></defs><g
|
||||
id="g816"><path
|
||||
id="path1-2-1"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#linearGradient13);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="m 37.175189,4.174075 c -2.15234,-7.4e-4 -4.0678,1.84724 -4.0671,4.1266 v 2.85212 c -0.073,-0.005 -0.14656,-0.007 -0.2202,-0.007 h -10.50012 -10.49855 c -0.0418,-7e-5 -0.0835,5.9e-4 -0.12516,0.002 v -2.78918 c -1.6e-4,-2.27807 -1.9592601,-4.12477 -4.1103801,-4.12494 -2.15111,1.8e-4 -4.20874,1.84687 -4.2089,4.12494 v 15.55127 c -4e-5,0.005 -0.0295,3.84339 2.173,7.60498 2.20396,3.76402 7.0382001,7.38257 14.4526701,7.38257 h 4.58067 c 7.4177,0 12.26918,-3.66617 14.50586,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.002,-0.0344 V 8.300605 c 7e-4,-2.27872 -2.10202,-4.12642 -4.25374,-4.1266 z m -2.00792,7.9252 v 11.59858 0.0286 c 0,0 -0.0664,2.0824 -1.31139,4.18416 -0.57202,0.96572 -1.44541,2.15762 -2.91767,2.99793 -1.47227,0.8403 -3.46066,1.33079 -6.27223,1.33079 h -4.58106 c -2.82381,0 -4.79864,-0.47938 -6.25697,-1.30429 -1.45833,-0.8249 -2.31357,-2.00343 -2.85901,-2.93496 -1.1966401,-2.04365 -1.2300401,-4.07193 -1.2300401,-4.07193 l -0.001,-0.0141 v -0.0157 -11.69637 l 1.96e-4,-0.0142 0.0035,-0.008 c 0.05128,0.0487 0.18806,0.16304 0.24192,0.20765 l 5.4247011,4.54513 5.51504,4.57144 c 0.65194,0.53945 2.27903,0.53945 2.93097,0 l 5.51504,-4.57144 5.487378,-4.57351 c 0.0199,-0.0164 0.04083,-0.0331 0.06003,-0.048 l 0.02765,-0.0215 z"
|
||||
sodipodi:nodetypes="cccccccccccssssccccccccssssssccccccccccccscc" /><path
|
||||
id="path1-2-1-9"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient816);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="M 3.6452555 7.14375 C 3.5159759 7.5278714 3.4447807 7.9357538 3.444751 8.3586629 L 3.444751 23.909652 C 3.444711 23.914652 3.4152451 27.753282 5.617745 31.514872 C 7.821705 35.278892 12.65614 38.897367 20.07061 38.897367 L 24.651208 38.897367 C 30.085144 38.897367 34.141887 36.930057 36.802405 34.39325 C 35.285228 33.174993 33.583741 31.797916 31.788757 30.3382 C 31.529773 30.540194 31.247156 30.732346 30.938163 30.908708 C 29.465893 31.749008 27.477765 32.239376 24.666195 32.239376 L 20.085079 32.239376 C 17.261269 32.239376 15.286427 31.759973 13.828097 30.935063 C 12.369767 30.110163 11.51428 28.931371 10.96884 27.999841 C 9.7721994 25.956191 9.7389404 23.928255 9.7389404 23.928255 L 9.7379069 23.914303 L 9.7379069 23.898283 L 9.7379069 12.201839 L 9.7379069 12.187887 L 9.7415243 12.179618 C 9.7928043 12.228318 9.92951 12.342748 9.98337 12.387358 L 15.408362 16.932817 L 20.923271 21.504114 C 21.007674 21.573954 21.108583 21.634775 21.221444 21.686532 C 16.15064 17.512631 11.679239 13.804108 9.750826 12.186336 C 7.4531167 10.290397 5.3700283 8.5696704 3.6452555 7.14375 z " /><path
|
||||
id="path1-2-1-7"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient815);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="M 41.226941 7.09104 C 39.508657 8.5115809 37.437441 10.222955 35.154443 12.106755 C 33.219453 13.730045 28.724331 17.458018 23.632149 21.649325 C 23.714466 21.60631 23.788932 21.557823 23.853841 21.504114 L 29.36875 16.932817 L 34.85627 12.358936 C 34.87617 12.342536 34.897015 12.325776 34.916215 12.310876 L 34.94412 12.289689 L 35.166846 12.09952 L 35.166846 23.697778 L 35.166846 23.726717 C 35.166846 23.726717 35.100288 25.808681 33.855298 27.910441 C 33.283278 28.876161 32.409906 30.068398 30.937646 30.908708 C 29.465376 31.749008 27.477248 32.239376 24.665678 32.239376 L 20.084562 32.239376 C 17.260752 32.239376 15.28591 31.759973 13.82758 30.935063 C 13.518898 30.760458 13.236992 30.570319 12.979569 30.369722 C 11.174016 31.837687 9.466344 33.219415 7.9488688 34.437174 C 10.591399 36.955726 14.638319 38.897367 20.070093 38.897367 L 24.650692 38.897367 C 32.068392 38.897367 36.920103 35.231484 39.156783 31.455444 C 41.393463 27.679404 41.426929 23.820251 41.426929 23.820251 L 41.428996 23.786145 L 41.428996 8.3007853 C 41.429125 7.8798785 41.357396 7.4736084 41.226941 7.09104 z " /></g><text
|
||||
xml:space="preserve"
|
||||
style="font-size:44.7887px;line-height:1.5;font-family:Roboto;-inkscape-font-specification:Roboto;letter-spacing:0.223944px;writing-mode:lr-tb;direction:ltr;fill:#f74e6a;fill-opacity:1;stroke:#ff0000;stroke-width:56.4265;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none"
|
||||
x="43.547977"
|
||||
y="38.744164"
|
||||
id="text13-7"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan13-7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';fill:#f74e6a;fill-opacity:1;stroke:none;stroke-width:56.4265"
|
||||
x="43.547977"
|
||||
y="38.744164">ltimo</tspan></text></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,14 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny-ps" viewBox="0 0 512 512">
|
||||
<title>Ultimo Email</title>
|
||||
<desc>Ultimo Email logo, for BIMI (SVG Tiny Portable/Secure)</desc>
|
||||
<defs>
|
||||
<linearGradient id="g" gradientUnits="userSpaceOnUse" x1="44.1352" y1="192.6008" x2="44.1352" y2="224.5123">
|
||||
<stop offset="0.202" stop-color="#f89629"/>
|
||||
<stop offset="1" stop-color="#f74176"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<defs><linearGradient id="g0" gradientUnits="userSpaceOnUse" x1="22.4348" y1="5.1873" x2="22.4348" y2="37.0988"><stop offset="0.2020" stop-color="#f89629" stop-opacity="1.0000"/><stop offset="1.0000" stop-color="#f74176" stop-opacity="1.0000"/></linearGradient><radialGradient id="g1" gradientUnits="userSpaceOnUse" cx="8.0343" cy="13.4530" r="16.6788"><stop offset="0.0000" stop-color="#fa7367" stop-opacity="1.0000"/><stop offset="1.0000" stop-color="#fa7367" stop-opacity="0.0000"/></radialGradient><radialGradient id="g2" gradientUnits="userSpaceOnUse" cx="35.7090" cy="12.0426" r="16.7401"><stop offset="0.0000" stop-color="#fab23b" stop-opacity="1.0000"/><stop offset="1.0000" stop-color="#fab23a" stop-opacity="0.0000"/></radialGradient></defs>
|
||||
<rect width="512" height="512" fill="#ffffff"/>
|
||||
<g transform="translate(97.2800,104.2299) scale(7.063024) translate(-21.70051,-187.41349)">
|
||||
<path fill="url(#g)" d="m 58.875622,191.58757 c -2.152336,-0.00074 -4.067804,1.84724 -4.067104,4.1266 v 2.85212 c -0.073,-0.005 -0.146556,-0.007 -0.220195,-0.007 H 44.088203 33.589648 c -0.04176,-0.00007 -0.0835,0.00059 -0.125155,0.002 v -2.78918 c -0.000166,-2.27807 -1.959264,-4.12477 -4.110377,-4.12494 -2.151113,0.00018 -4.208743,1.84687 -4.208908,4.12494 v 15.55127 c -0.000039,0.005 -0.02954,3.84339 2.173004,7.60498 2.20396,3.76402 7.038201,7.38257 14.452668,7.38257 h 4.580673 c 7.417703,0 12.26918,-3.66617 14.505859,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.0016,-0.0344 V 195.7141 c 0.0007,-2.27872 -2.102019,-4.12642 -4.253744,-4.1266 z m -2.007917,7.94794 v 11.57584 0.0286 c 0,0 -0.06644,2.0824 -1.311391,4.18416 -0.572022,0.96572 -1.445415,2.15762 -2.917676,2.99793 -1.472263,0.8403 -3.460652,1.33079 -6.272222,1.33079 H 41.78535 c -2.82381,0 -4.798635,-0.47938 -6.256969,-1.30429 -1.458334,-0.8249 -2.313565,-2.00343 -2.85901,-2.93496 -1.196636,-2.04365 -1.230039,-4.07193 -1.230039,-4.07193 l -0.0011,-0.0141 v -0.0157 -11.69637 l 0.02191,0.0178 0.000782,0.001 c 0.03515,0.0487 0.07994,0.0958 0.133761,0.14041 l 5.513859,4.57144 5.515036,4.57144 c 0.651946,0.53945 2.279028,0.53945 2.930974,0 l 5.515034,-4.57144 5.514252,-4.57144 c 0.01986,-0.0164 0.03852,-0.0331 0.05593,-0.0501 l 0.000782,-0.00082 z"/>
|
||||
</g>
|
||||
<g transform="matrix(7.081810,0,0,7.081810,96.1936,104.0546)"><g transform="matrix(1,0,0,1,0.128676,-0.079965)"><path fill="url(#g0)" d="M37.1752,4.1741C35.0228,4.1733 33.1074,6.0213 33.1081,8.3007L33.1081,11.1528C33.0351,11.1478 32.9615,11.1458 32.8879,11.1458L22.3878,11.1458L11.8892,11.1458C11.8474,11.1457 11.8057,11.1464 11.7641,11.1478L11.7641,8.3586C11.7639,6.0805 9.8048,4.2338 7.6537,4.2337C5.5026,4.2339 3.4449,6.0805 3.4448,8.3586L3.4448,23.9099C3.4447,23.9149 3.4153,27.7533 5.6178,31.5149C7.8217,35.2789 12.6560,38.8974 20.0704,38.8974L24.6511,38.8974C32.0688,38.8974 36.9203,35.2313 39.1570,31.4552C41.3937,27.6792 41.4274,23.8204 41.4274,23.8204L41.4294,23.7860L41.4294,8.3006C41.4301,6.0219 39.3273,4.1742 37.1756,4.1740ZM35.1673,12.0993L35.1673,23.6979L35.1673,23.7265C35.1673,23.7265 35.1009,25.8089 33.8559,27.9106C33.2839,28.8763 32.4105,30.0682 30.9382,30.9085C29.4659,31.7488 27.4775,32.2393 24.6660,32.2393L20.0849,32.2393C17.2611,32.2393 15.2863,31.7600 13.8279,30.9350C12.3696,30.1101 11.5144,28.9316 10.9689,28.0001C9.7723,25.9564 9.7389,23.9282 9.7389,23.9282L9.7379,23.9141L9.7379,23.8984L9.7379,12.2020L9.7381,12.1878L9.7416,12.1798C9.7929,12.2285 9.9297,12.3428 9.9835,12.3874L15.4082,16.9326L20.9233,21.5040C21.5752,22.0435 23.2023,22.0435 23.8542,21.5040L29.3693,16.9326L34.8566,12.3591C34.8765,12.3427 34.8975,12.3260 34.9167,12.3111L34.9443,12.2896Z"/><g transform="matrix(-0.29271702,0.00410386,-0.01334442,-0.95181978,11.840139,23.950941)"><path fill="url(#g1)" d="M27.1856,17.7752C27.6455,17.3736 27.9083,16.9462 27.9286,16.5020L28.6733,0.1670C28.6737,0.1618 28.9581,-3.8700 21.6154,-7.8536C14.2678,-11.8398 -2.0714,-15.7119 -27.3962,-15.8211L-43.0417,-15.8886C-61.6019,-15.9686 -75.5523,-13.9619 -84.7610,-11.3363C-79.6373,-10.0343 -73.8916,-8.5628 -67.8306,-7.0030C-66.9363,-7.2114 -65.9618,-7.4091 -64.8980,-7.5898C-59.8291,-8.4508 -53.0149,-8.9366 -43.4117,-8.8952L-27.7645,-8.8277C-18.1195,-8.7861 -11.3972,-8.2535 -6.4556,-7.3655C-1.5141,-6.4775 1.3515,-5.2267 3.1699,-4.2402C7.1593,-2.0759 7.1758,0.0548 7.1758,0.0548L7.1786,0.0694L7.1778,0.0863L6.6177,12.3724L6.6171,12.3870L6.6043,12.3957C6.4315,12.3438 5.9700,12.2216 5.7882,12.1739L-12.5237,7.3194L-31.1415,2.4364C-31.4264,2.3618 -31.7682,2.2965 -32.1512,2.2404C-15.0312,6.6994 0.0637,10.6607 6.5729,12.3885C14.3301,14.4138 21.3627,16.2520 27.1856,17.7752Z"/></g><g transform="matrix(0.25712152,0.00260463,-0.00969379,0.95694375,26.644192,0.973013)"><path fill="url(#g2)" d="M56.9506,6.2383C50.3245,7.7408 42.3373,9.5509 33.5334,11.5434C26.0725,13.2601 8.7387,17.2029 -10.8988,21.6363C-10.5803,21.5905 -10.2927,21.5390 -10.0424,21.4822L11.2240,16.6473L32.3838,11.8101C32.4605,11.7927 32.5409,11.7750 32.6150,11.7592L32.7226,11.7368L33.5813,11.5357L34.0382,23.6546L34.0393,23.6848C34.0393,23.6848 33.8625,25.8609 29.1038,28.0702C26.9173,29.0853 23.5679,30.3403 17.8757,31.2340C12.1834,32.1276 4.4713,32.6610 -6.4624,32.6907L-24.2775,32.7392C-35.2588,32.7691 -42.9575,32.2891 -48.6611,31.4426C-49.8684,31.2634 -50.9722,31.0677 -51.9812,30.8609C-58.9448,32.4138 -65.5312,33.8756 -71.3844,35.1641C-61.0089,37.7678 -45.1947,39.7537 -24.0715,39.6962L-6.2584,39.6477C22.5876,39.5692 41.3106,35.6874 49.8599,31.7182C58.4092,27.7490 58.3873,23.7163 58.3873,23.7163L58.3941,23.6806L57.7841,7.5002C57.7679,7.0604 57.4730,6.6366 56.9506,6.2383Z"/></g></g></g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 22 KiB |
@@ -7,7 +7,7 @@
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "any",
|
||||
"background_color": "#ffffff",
|
||||
"background_color": "#1b1e20",
|
||||
"theme_color": "#f3f4f6",
|
||||
"categories": ["productivity", "business"],
|
||||
"icons": [
|
||||
|
||||
@@ -26,9 +26,87 @@
|
||||
x2="54.340946"
|
||||
y2="162.66415"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /></defs><g
|
||||
id="layer1"
|
||||
transform="translate(-21.70051,-187.41349)"><path
|
||||
id="path1-2"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;opacity:1;vector-effect:none;fill:url(#linearGradient12);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||
d="m 58.875622,191.58757 c -2.152336,-7.4e-4 -4.067804,1.84724 -4.067104,4.1266 v 2.85212 c -0.073,-0.005 -0.146556,-0.007 -0.220195,-0.007 H 44.088203 33.589648 c -0.04176,-7e-5 -0.0835,5.9e-4 -0.125155,0.002 v -2.78918 c -1.66e-4,-2.27807 -1.959264,-4.12477 -4.110377,-4.12494 -2.151113,1.8e-4 -4.208743,1.84687 -4.208908,4.12494 v 15.55127 c -3.9e-5,0.005 -0.02954,3.84339 2.173004,7.60498 2.20396,3.76402 7.038201,7.38257 14.452668,7.38257 h 4.580673 c 7.417703,0 12.26918,-3.66617 14.505859,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.0016,-0.0344 V 195.7141 c 7e-4,-2.27872 -2.102019,-4.12642 -4.253744,-4.1266 z m -2.007917,7.94794 v 11.57584 0.0286 c 0,0 -0.06644,2.0824 -1.311391,4.18416 -0.572022,0.96572 -1.445415,2.15762 -2.917676,2.99793 -1.472263,0.8403 -3.460652,1.33079 -6.272222,1.33079 H 41.78535 c -2.82381,0 -4.798635,-0.47938 -6.256969,-1.30429 -1.458334,-0.8249 -2.313565,-2.00343 -2.85901,-2.93496 -1.196636,-2.04365 -1.230039,-4.07193 -1.230039,-4.07193 l -0.0011,-0.0141 v -0.0157 -11.69637 l 0.02191,0.0178 7.82e-4,10e-4 c 0.03515,0.0487 0.07994,0.0958 0.133761,0.14041 l 5.513859,4.57144 5.515036,4.57144 c 0.651946,0.53945 2.279028,0.53945 2.930974,0 l 5.515034,-4.57144 5.514252,-4.57144 c 0.01986,-0.0164 0.03852,-0.0331 0.05593,-0.0501 l 7.82e-4,-8.2e-4 z" /></g></svg>
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,3.0076311,94.135157)" /><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="-1000"
|
||||
y="-1000"
|
||||
width="3000"
|
||||
height="3000"
|
||||
id="mask1788"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1788" /></mask><linearGradient
|
||||
xlink:href="#linearGradient1769"
|
||||
id="linearGradient1789"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="37.71608"
|
||||
y1="123.22854"
|
||||
x2="27.709011"
|
||||
y2="135.24788" /><linearGradient
|
||||
id="linearGradient1769"><stop
|
||||
style="stop-color:#ffe3ac;stop-opacity:0.36078355;"
|
||||
offset="0.00003701"
|
||||
id="stop1769" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop1770" /></linearGradient><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="-1000"
|
||||
y="-1000"
|
||||
width="3000"
|
||||
height="3000"
|
||||
id="mask1776-6"><path
|
||||
style="fill:url(#linearGradient1789);fill-opacity:1;stroke-width:0.2;stroke-linecap:round"
|
||||
d="m 18.20332,107.02297 c 0,0 1.930731,1.59986 4.989281,4.12846 1.725315,1.42637 3.809507,3.14827 6.108453,5.04523 5.657506,4.74616 33.20207,27.48506 33.558689,27.18811 0.241178,-0.20083 -16.275384,9.86387 -16.275384,9.86387 L 17.979141,140.69463 Z"
|
||||
id="path1776-1" /></mask><linearGradient
|
||||
xlink:href="#linearGradient11"
|
||||
id="linearGradient13-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.75684298,0,0,0.80151105,-18.692802,-93.278335)"
|
||||
x1="54.340946"
|
||||
y1="122.84999"
|
||||
x2="54.340946"
|
||||
y2="162.66415" /><radialGradient
|
||||
xlink:href="#linearGradient8"
|
||||
id="radialGradient816"
|
||||
cx="8.0343275"
|
||||
cy="13.452971"
|
||||
fx="8.0343275"
|
||||
fy="13.452971"
|
||||
r="16.678839"
|
||||
gradientTransform="matrix(-0.29271702,0.00410386,-0.01334442,-0.95181978,11.840139,23.950941)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient8"><stop
|
||||
style="stop-color:#fa7367;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8" /><stop
|
||||
style="stop-color:#fa7367;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop9" /></linearGradient><radialGradient
|
||||
xlink:href="#linearGradient6"
|
||||
id="radialGradient815"
|
||||
cx="35.709007"
|
||||
cy="12.042645"
|
||||
fx="35.709007"
|
||||
fy="12.042645"
|
||||
r="16.740065"
|
||||
gradientTransform="matrix(0.25712152,0.00260463,-0.00969379,0.95694375,26.644192,0.97301292)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
id="linearGradient6"><stop
|
||||
style="stop-color:#fab23b;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6" /><stop
|
||||
style="stop-color:#fab23a;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7" /></linearGradient></defs><g
|
||||
id="g816"
|
||||
transform="translate(0.128676,-0.079965)"><path
|
||||
id="path1-2-1-1"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#linearGradient13-6);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="m 37.175189,4.174075 c -2.15234,-7.4e-4 -4.0678,1.84724 -4.0671,4.1266 v 2.85212 c -0.073,-0.005 -0.14656,-0.007 -0.2202,-0.007 h -10.50012 -10.49855 c -0.0418,-7e-5 -0.0835,5.9e-4 -0.12516,0.002 v -2.78918 c -1.6e-4,-2.27807 -1.9592601,-4.12477 -4.1103801,-4.12494 -2.15111,1.8e-4 -4.20874,1.84687 -4.2089,4.12494 v 15.55127 c -4e-5,0.005 -0.0295,3.84339 2.173,7.60498 2.20396,3.76402 7.0382001,7.38257 14.4526701,7.38257 h 4.58067 c 7.4177,0 12.26918,-3.66617 14.50586,-7.44221 2.23668,-3.77604 2.27039,-7.63481 2.27039,-7.63481 l 0.002,-0.0344 V 8.300605 c 7e-4,-2.27872 -2.10202,-4.12642 -4.25374,-4.1266 z m -2.00792,7.9252 v 11.59858 0.0286 c 0,0 -0.0664,2.0824 -1.31139,4.18416 -0.57202,0.96572 -1.44541,2.15762 -2.91767,2.99793 -1.47227,0.8403 -3.46066,1.33079 -6.27223,1.33079 h -4.58106 c -2.82381,0 -4.79864,-0.47938 -6.25697,-1.30429 -1.45833,-0.8249 -2.31357,-2.00343 -2.85901,-2.93496 -1.1966401,-2.04365 -1.2300401,-4.07193 -1.2300401,-4.07193 l -0.001,-0.0141 v -0.0157 -11.69637 l 1.96e-4,-0.0142 0.0035,-0.008 c 0.05128,0.0487 0.18806,0.16304 0.24192,0.20765 l 5.4247011,4.54513 5.51504,4.57144 c 0.65194,0.53945 2.27903,0.53945 2.93097,0 l 5.51504,-4.57144 5.487378,-4.57351 c 0.0199,-0.0164 0.04083,-0.0331 0.06003,-0.048 l 0.02765,-0.0215 z" /><path
|
||||
id="path1-2-1-9"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient816);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="M 3.6452555,7.14375 C 3.5159759,7.5278714 3.4447807,7.9357538 3.444751,8.3586629 V 23.909652 c -4e-5,0.005 -0.029506,3.84363 2.172994,7.60522 2.20396,3.76402 7.038395,7.382495 14.452865,7.382495 h 4.580598 c 5.433936,0 9.490679,-1.96731 12.151197,-4.504117 -1.517177,-1.218257 -3.218664,-2.595334 -5.013648,-4.05505 -0.258984,0.201994 -0.541601,0.394146 -0.850594,0.570508 -1.47227,0.8403 -3.460398,1.330668 -6.271968,1.330668 h -4.581116 c -2.82381,0 -4.798652,-0.479403 -6.256982,-1.304313 -1.45833,-0.8249 -2.313817,-2.003692 -2.859257,-2.935222 -1.1966406,-2.04365 -1.2298996,-4.071586 -1.2298996,-4.071586 l -0.00103,-0.01395 v -0.01602 -11.696444 -0.01395 l 0.00362,-0.0083 c 0.05128,0.0487 0.1879857,0.16313 0.2418457,0.20774 l 5.4249919,4.545459 5.514909,4.571297 c 0.0844,0.06984 0.185312,0.130661 0.298173,0.182418 C 16.15064,17.512631 11.679239,13.804108 9.750826,12.186336 7.4531167,10.290397 5.3700283,8.5696704 3.6452555,7.14375 Z" /><path
|
||||
id="path1-2-1-7"
|
||||
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:url(#radialGradient815);fill-opacity:1;stroke-width:0.778856;stroke-linecap:round;enable-background:accumulate;stop-color:#000000"
|
||||
d="m 41.226941,7.09104 c -1.718284,1.4205409 -3.7895,3.131915 -6.072498,5.015715 -1.93499,1.62329 -6.430112,5.351263 -11.522294,9.54257 0.08232,-0.04302 0.156783,-0.0915 0.221692,-0.145211 l 5.514909,-4.571297 5.48752,-4.573881 c 0.0199,-0.0164 0.04075,-0.03316 0.05994,-0.04806 l 0.0279,-0.02119 0.222726,-0.190169 v 11.598258 0.02894 c 0,0 -0.06656,2.081964 -1.311548,4.183724 -0.57202,0.96572 -1.445392,2.157957 -2.917652,2.998267 -1.47227,0.8403 -3.460398,1.330668 -6.271968,1.330668 h -4.581116 c -2.82381,0 -4.798652,-0.479403 -6.256982,-1.304313 -0.308682,-0.174605 -0.590588,-0.364744 -0.848011,-0.565341 -1.805553,1.467965 -3.513225,2.849693 -5.0307002,4.067452 2.6425302,2.518552 6.6894502,4.460193 12.1212242,4.460193 h 4.580599 c 7.4177,0 12.269411,-3.665883 14.506091,-7.441923 2.23668,-3.77604 2.270146,-7.635193 2.270146,-7.635193 l 0.0021,-0.03411 V 8.3007853 C 41.429125,7.8798785 41.357396,7.4736084 41.226941,7.09104 Z" /></g></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 7.9 KiB |
@@ -2,10 +2,10 @@ import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tansta
|
||||
import { useEffect, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
import { useT } from "../i18n";
|
||||
import { languageName, useLocale, useT } from "../i18n";
|
||||
import { api, ApiError } from "../lib/api";
|
||||
import { useMe } from "../lib/auth";
|
||||
import type { AdminMail, AdminUser } from "../lib/types";
|
||||
import type { AdminMail, AdminTranslation, AdminUser } from "../lib/types";
|
||||
import { useConfirm } from "../components/AppDialog";
|
||||
|
||||
const GIB = 1024 ** 3;
|
||||
@@ -44,8 +44,9 @@ export function AdminApp() {
|
||||
<Users selfId={me.data.id} />
|
||||
</div>
|
||||
{/* The divider runs the full height of the taller column. */}
|
||||
<div className="min-w-0 lg:border-l lg:border-app-border lg:pl-12">
|
||||
<div className="min-w-0 space-y-10 lg:border-l lg:border-app-border lg:pl-12">
|
||||
<SystemMail />
|
||||
<Translation />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -287,6 +288,136 @@ function Panel({ handle }: { handle: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
/** Email translation's languages: installed ones (removable, but English),
|
||||
* downloads in progress, and any language Mozilla has models for to add. */
|
||||
function Translation() {
|
||||
const t = useT();
|
||||
const { locale } = useLocale();
|
||||
const queryClient = useQueryClient();
|
||||
const [confirm, confirmDialog] = useConfirm();
|
||||
const [adding, setAdding] = useState("");
|
||||
const info = useQuery({
|
||||
queryKey: ["adminTranslation"],
|
||||
queryFn: api.adminTranslation,
|
||||
// While something downloads, follow its progress.
|
||||
refetchInterval: (q) =>
|
||||
Object.keys((q.state.data as AdminTranslation | undefined)?.installing ?? {}).length ? 1500 : false,
|
||||
});
|
||||
const done = (data: AdminTranslation) => {
|
||||
queryClient.setQueryData(["adminTranslation"], data);
|
||||
void queryClient.invalidateQueries({ queryKey: ["translation-languages"] });
|
||||
};
|
||||
const install = useMutation({
|
||||
mutationFn: api.installTranslationLanguage,
|
||||
onSuccess: (data) => {
|
||||
done(data);
|
||||
setAdding("");
|
||||
},
|
||||
});
|
||||
const remove = useMutation({ mutationFn: api.removeTranslationLanguage, onSuccess: done });
|
||||
|
||||
const name = (code: string) => languageName(code, locale);
|
||||
const data = info.data;
|
||||
const busy = install.isPending || remove.isPending;
|
||||
const installing = Object.entries(data?.installing ?? {});
|
||||
const addable = (data?.available ?? [])
|
||||
.filter((c) => !data?.installed.includes(c) && !(c in (data?.installing ?? {})))
|
||||
.sort((a, b) => name(a).localeCompare(name(b), locale));
|
||||
const error = (install.error ?? remove.error) as unknown;
|
||||
|
||||
return (
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-lg font-semibold">{t("admin.translation")}</h2>
|
||||
<p className="text-xs text-app-faint">{t("admin.translationHelp")}</p>
|
||||
{info.error instanceof ApiError && <p className="text-sm text-red-500">{info.error.message}</p>}
|
||||
{data && !data.enabled && <p className="text-sm text-amber-600">{t("admin.translationOff")}</p>}
|
||||
{data?.enabled && !data.reachable && (
|
||||
<p className="text-sm text-amber-600">{t("admin.translationUnreachable")}</p>
|
||||
)}
|
||||
{data?.reachable && (
|
||||
<>
|
||||
<ul className="divide-y divide-app-border rounded border border-app-border">
|
||||
{[...data.installed]
|
||||
.sort((a, b) => name(a).localeCompare(name(b), locale))
|
||||
.map((code) => (
|
||||
<li key={code} className="flex items-center justify-between px-3 py-2 text-sm">
|
||||
<span>
|
||||
{name(code)} <span className="text-xs text-app-faint">{code}</span>
|
||||
</span>
|
||||
{code === "en" ? (
|
||||
<span className="text-xs text-app-faint">{t("admin.translationAlways")}</span>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={busy}
|
||||
className="rounded border border-app-border px-2 py-0.5 text-xs hover:bg-app-hover disabled:opacity-50"
|
||||
onClick={async () => {
|
||||
const ok = await confirm({
|
||||
title: t("admin.translationRemoveTitle", { language: name(code) }),
|
||||
message: t("admin.translationRemoveConfirm"),
|
||||
confirmLabel: t("admin.translationRemove"),
|
||||
danger: true,
|
||||
});
|
||||
if (ok) remove.mutate(code);
|
||||
}}
|
||||
>
|
||||
{t("admin.translationRemove")}
|
||||
</button>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
{installing.map(([code, p]) => (
|
||||
<li key={code} className="flex items-center justify-between px-3 py-2 text-sm text-app-muted">
|
||||
<span>{name(code)}</span>
|
||||
<span className="text-xs tabular-nums">
|
||||
{t("admin.translationInstalling", {
|
||||
percent: p.total ? Math.floor((p.done / p.total) * 100) : 0,
|
||||
})}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{Object.entries(data.errors).map(([code, why]) => (
|
||||
<p key={code} className="text-xs text-red-500">
|
||||
{t("admin.translationFailed", { language: name(code) })} {why}
|
||||
</p>
|
||||
))}
|
||||
{addable.length > 0 ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
className="min-w-0 flex-1 rounded border border-app-border bg-app-surface px-2 py-1.5 text-sm"
|
||||
value={adding}
|
||||
onChange={(e) => setAdding(e.target.value)}
|
||||
>
|
||||
<option value="">{t("admin.translationChoose")}</option>
|
||||
{addable.map((code) => (
|
||||
<option key={code} value={code}>
|
||||
{name(code)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!adding || busy}
|
||||
className="rounded bg-app-accent px-3 py-1.5 text-sm font-medium text-app-accent-fg hover:opacity-90 disabled:opacity-50"
|
||||
onClick={() => install.mutate(adding)}
|
||||
>
|
||||
{t("admin.translationInstall")}
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
data.available.length === 0 && (
|
||||
<p className="text-xs text-app-faint">{t("admin.translationCatalogueOffline")}</p>
|
||||
)
|
||||
)}
|
||||
{error instanceof ApiError && <p className="text-xs text-red-500">{error.message}</p>}
|
||||
</>
|
||||
)}
|
||||
{confirmDialog}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
type MailDraft = Omit<AdminMail, "has_password" | "configured">;
|
||||
|
||||
/** The SMTP account the server sends password-reset links from. */
|
||||
|
||||
@@ -478,7 +478,7 @@ function MessageItem({
|
||||
: [];
|
||||
const offerTranslate =
|
||||
translateCodes.length > 0 &&
|
||||
(translateTo !== null || needsTranslation(language, locale));
|
||||
(translateTo !== null || needsTranslation(language, locale, translateCodes));
|
||||
const target = translateCodes.find((c) => sameLanguage(c, locale)) ?? null;
|
||||
const replyBtn = (kind: string, label: string, icon: string) => (
|
||||
<button
|
||||
|
||||
@@ -691,6 +691,20 @@ export const en = {
|
||||
"admin.testTo": "Send a test email to",
|
||||
"admin.sendTest": "Send test",
|
||||
"admin.testSent": "Test email sent.",
|
||||
"admin.translation": "Email translation",
|
||||
"admin.translationHelp":
|
||||
"Languages email can be translated between, all on this server (Mozilla's Firefox Translations models). Each language is about 70 MB: models to and from English, through which other pairs go.",
|
||||
"admin.translationOff": "Translation is off on this server (TRANSLATOR_URL is empty).",
|
||||
"admin.translationUnreachable": "The translation service is not answering. It may still be starting.",
|
||||
"admin.translationAlways": "always installed",
|
||||
"admin.translationRemove": "Remove",
|
||||
"admin.translationRemoveTitle": "Remove {language}?",
|
||||
"admin.translationRemoveConfirm": "Its models are deleted. Mail in this language can no longer be translated until it is installed again.",
|
||||
"admin.translationInstalling": "downloading… {percent}%",
|
||||
"admin.translationFailed": "Installing {language} failed:",
|
||||
"admin.translationChoose": "Add a language…",
|
||||
"admin.translationInstall": "Install",
|
||||
"admin.translationCatalogueOffline": "Mozilla's list of languages can't be reached right now, so no more can be added.",
|
||||
"admin.users": "Users",
|
||||
"admin.userSearch": "Search by login, email address or name…",
|
||||
"admin.noUsers": "No users match.",
|
||||
|
||||
@@ -68,9 +68,14 @@ export function sameLanguage(a: string, b: string): boolean {
|
||||
}
|
||||
|
||||
/** Whether a message in ``languages`` ("zh-Hans,pl,en", as the server found
|
||||
* them) has a part that is not in ``locale``: then it can be translated. */
|
||||
export function needsTranslation(languages: string, locale: string): boolean {
|
||||
return splitLanguages(languages).some((code) => !sameLanguage(code, locale));
|
||||
* them) has a part that is not in ``locale`` but is in ``installed`` (the
|
||||
* languages translation has): then it can be translated. */
|
||||
export function needsTranslation(languages: string, locale: string, installed: string[]): boolean {
|
||||
return splitLanguages(languages).some(
|
||||
(code) =>
|
||||
!sameLanguage(code, locale) &&
|
||||
installed.some((have) => have === code || (!have.includes("-") && sameLanguage(have, code))),
|
||||
);
|
||||
}
|
||||
|
||||
/** "zh-Hans,pl,en" → ["zh-Hans", "pl", "en"]. */
|
||||
|
||||
@@ -702,6 +702,20 @@ export const pl: Catalog = {
|
||||
"admin.testTo": "Wyślij testowy e-mail do",
|
||||
"admin.sendTest": "Wyślij test",
|
||||
"admin.testSent": "Wysłano testowy e-mail.",
|
||||
"admin.translation": "Tłumaczenie poczty",
|
||||
"admin.translationHelp":
|
||||
"Języki, między którymi można tłumaczyć pocztę, w całości na tym serwerze (modele Firefox Translations od Mozilli). Każdy język to około 70 MB: modele z angielskiego i na angielski, przez który idą pozostałe pary.",
|
||||
"admin.translationOff": "Tłumaczenie jest wyłączone na tym serwerze (TRANSLATOR_URL jest pusty).",
|
||||
"admin.translationUnreachable": "Usługa tłumaczenia nie odpowiada. Może jeszcze się uruchamia.",
|
||||
"admin.translationAlways": "zawsze zainstalowany",
|
||||
"admin.translationRemove": "Usuń",
|
||||
"admin.translationRemoveTitle": "Usunąć: {language}?",
|
||||
"admin.translationRemoveConfirm": "Jego modele zostaną usunięte. Poczty w tym języku nie będzie można tłumaczyć, dopóki nie zostanie zainstalowany ponownie.",
|
||||
"admin.translationInstalling": "pobieranie… {percent}%",
|
||||
"admin.translationFailed": "Instalacja nie powiodła się: {language}.",
|
||||
"admin.translationChoose": "Dodaj język…",
|
||||
"admin.translationInstall": "Zainstaluj",
|
||||
"admin.translationCatalogueOffline": "Lista języków Mozilli jest teraz niedostępna, więc nie można dodać kolejnych.",
|
||||
"admin.users": "Użytkownicy",
|
||||
"admin.userSearch": "Szukaj po loginie, adresie e-mail lub nazwie…",
|
||||
"admin.noUsers": "Brak pasujących użytkowników.",
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
AppPassword,
|
||||
AccountDetail,
|
||||
AdminMail,
|
||||
AdminTranslation,
|
||||
AdminSettings,
|
||||
AdminUser,
|
||||
AccountOut,
|
||||
@@ -136,6 +137,11 @@ export const api = {
|
||||
deleteAdminUser: (id: string) =>
|
||||
apiFetch<{ status: string }>(`/admin/users/${id}`, { method: "DELETE" }),
|
||||
adminMail: () => apiFetch<AdminMail>("/admin/mail"),
|
||||
adminTranslation: () => apiFetch<AdminTranslation>("/admin/translation"),
|
||||
installTranslationLanguage: (code: string) =>
|
||||
apiFetch<AdminTranslation>(`/admin/translation/languages/${code}`, { method: "POST" }),
|
||||
removeTranslationLanguage: (code: string) =>
|
||||
apiFetch<AdminTranslation>(`/admin/translation/languages/${code}`, { method: "DELETE" }),
|
||||
// PUT merges: omit smtp_password to keep the stored one, "" to remove it.
|
||||
saveAdminMail: (body: Partial<Omit<AdminMail, "has_password" | "configured">> & { smtp_password?: string }) =>
|
||||
apiFetch<AdminMail>("/admin/mail", { method: "PUT", body: JSON.stringify(body) }),
|
||||
|
||||
@@ -42,6 +42,18 @@ export interface AdminMail {
|
||||
configured: boolean;
|
||||
}
|
||||
|
||||
/** Email translation's languages on the translator service (admin panel). */
|
||||
export interface AdminTranslation {
|
||||
enabled: boolean;
|
||||
reachable: boolean;
|
||||
installed: string[];
|
||||
/** Downloads in progress: bytes done of total (total 0 until known). */
|
||||
installing: Record<string, { done: number; total: number }>;
|
||||
/** Languages Mozilla has models for; empty when the catalogue is out of reach. */
|
||||
available: string[];
|
||||
errors: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface AdminSettings {
|
||||
registration_open: boolean;
|
||||
/** Quota given to users created from now on; existing mailboxes keep theirs. */
|
||||
|
||||