[mob][photos] Resolve merge conflicts and merge main

This commit is contained in:
ashilkn
2024-10-18 20:27:42 +05:30
527 changed files with 23255 additions and 7761 deletions

BIN
.github/assets/obtainium-badge.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -42,11 +42,12 @@ You can also clone this repository and choose to self-host.
<div align="center">
[<img height="42" src=".github/assets/app-store-badge.svg">](https://apps.apple.com/app/id1542026904)
[<img height="42" src=".github/assets/play-store-badge.png">](https://play.google.com/store/apps/details?id=io.ente.photos)
[<img height="42" src=".github/assets/f-droid-badge.png">](https://f-droid.org/packages/io.ente.photos.fdroid/)
[<img height="42" src=".github/assets/desktop-badge.png">](https://ente.io/download/desktop)
[<img height="42" src=".github/assets/web-badge.svg">](https://web.ente.io)
[<img height="40" src=".github/assets/app-store-badge.svg">](https://apps.apple.com/app/id1542026904)
[<img height="40" src=".github/assets/play-store-badge.png">](https://play.google.com/store/apps/details?id=io.ente.photos)
[<img height="40" src=".github/assets/f-droid-badge.png">](https://f-droid.org/packages/io.ente.photos.fdroid/)
[<img height="40" src=".github/assets/obtainium-badge.png">](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.photos.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Photos%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-photos*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D)
[<img height="40" src=".github/assets/desktop-badge.png">](https://ente.io/download/desktop)
[<img height="40" src=".github/assets/web-badge.svg">](https://web.ente.io)
</div>
@@ -67,11 +68,12 @@ want to give back, please check out Ente Photos or spread the word.
<div align="center">
[<img height="42" src=".github/assets/app-store-badge.svg">](https://apps.apple.com/app/id6444121398)
[<img height="42" src=".github/assets/play-store-badge.png">](https://play.google.com/store/apps/details?id=io.ente.auth)
[<img height="42" src=".github/assets/f-droid-badge.png">](https://f-droid.org/packages/io.ente.auth/)
[<img height="42" src=".github/assets/desktop-badge.png">](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4)
[<img height="42" src=".github/assets/web-badge.svg">](https://auth.ente.io)
[<img height="40" src=".github/assets/app-store-badge.svg">](https://apps.apple.com/app/id6444121398)
[<img height="40" src=".github/assets/play-store-badge.png">](https://play.google.com/store/apps/details?id=io.ente.auth)
[<img height="40" src=".github/assets/f-droid-badge.png">](https://f-droid.org/packages/io.ente.auth/)
[<img height="40" src=".github/assets/obtainium-badge.png">](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.auth.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Auth%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-auth*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D)
[<img height="40" src=".github/assets/desktop-badge.png">](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4)
[<img height="40" src=".github/assets/web-badge.svg">](https://auth.ente.io)
</div>

View File

@@ -20,6 +20,12 @@
"title": "airtm",
"hex": "000000"
},
{
"title": "aliyun",
"altNames": [
"阿里云"
]
},
{
"title": "Amazon"
},
@@ -30,6 +36,16 @@
{
"title": "AscendEX"
},
{
"title": "BaiduCloud",
"altNames": [
"百度云",
"baiduyun"
]
},
{
"title": "Band"
},
{
"title": "Battle.net",
"slug": "battlenet",
@@ -38,12 +54,25 @@
"Blizzard"
]
},
{
"title": "BBS.NGA",
"altNames": [
"NGA玩家社区",
"NGA社区"
]
},
{
"title": "Bethesda",
"altNames": [
"Bethesda Softworks"
]
},
{
"title": "Binance",
"altNames": [
"币安"
]
},
{
"title": "BinanceUS",
"slug": "binance_us",
@@ -327,6 +356,12 @@
"title": "Jagex",
"hex": "D3D800"
},
{
"title": "jianguoyun",
"altNames": [
"坚果云"
]
},
{
"title": "Kagi"
},
@@ -356,9 +391,23 @@
"title": "La Poste",
"slug": "laposte"
},
{
"title": "Lark",
"altNames": [
"飞书"
]
},
{
"title": "Letterboxd"
},
{
"title": "Linux.Do",
"slug": "LINUX_DO",
"altNames": [
"LINUX DO",
"LinxDo"
]
},
{
"title": "Local",
"slug": "local_wp",
@@ -446,6 +495,13 @@
"title": "Name.com",
"slug": "name_com"
},
{
"title": "NeteaseMail",
"altNames": [
"网易邮箱",
"Mail.163"
]
},
{
"title": "NextDNS"
},
@@ -459,6 +515,12 @@
"title": "ngrok",
"hex": "858585"
},
{
"title": "Nintendo",
"altNames": [
"任天堂"
]
},
{
"title": "Njalla"
},
@@ -487,7 +549,10 @@
},
{
"title": "okx",
"hex": "000000"
"hex": "000000",
"altNames": [
"欧易"
]
},
{
"title": "Parsec"
@@ -495,6 +560,11 @@
{
"title": "PayPal"
},
{
"title": "PBTech",
"slug": "pbtech",
"hex": "f08222"
},
{
"title": "pCloud"
},
@@ -531,10 +601,21 @@
{
"title": "Proxmox"
},
{
"title": "qiniuyun",
"altNames": [
"七牛云",
"qiniu"
]
},
{
"title": "Real-Debrid",
"slug": "real_debrid"
},
{
"title": "RealMe",
"slug": "realme"
},
{
"title": "Registro br",
"slug": "registro_br",
@@ -580,6 +661,13 @@
{
"title": "SimpleLogin"
},
{
"title": "Simplicity",
"altNames": [
"simplicitynz",
"simplicity.kiwi"
]
},
{
"title": "Sipgate"
},
@@ -625,6 +713,14 @@
{
"title": "TCPShield"
},
{
"title": "tencent cloud",
"slug": "tencent_cloud"
"altNames": [
"腾讯云",
"tencentcloud"
]
},
{
"title": "Techlore",
"altNames": [
@@ -646,6 +742,12 @@
{
"title": "Titan"
},
{
"title": "tianyiyun",
"altNames": [
"天翼云"
]
},
{
"title": "TorGuard"
},
@@ -696,6 +798,12 @@
"title": "Vikunja"
},
{
"title": "volcengine",
"altNames": [
"火山引擎"
]
},
{
"title": "WARGAMING.NET"
},
{

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340333809" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8815" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M245.824 651.52V459.776c0-37.44-18.56-72.512-51.2-91.264L64.32 291.328v465.472c0 11.712 6.976 23.36 16.256 28.096l400.32 233.856v-152c0-37.44-18.624-72.512-51.2-91.264L262.144 679.68c-9.344-7.04-16.32-16.384-16.32-28.096" fill="#008DD5" p-id="8816"></path><path d="M760.192 679.616l-167.616 98.24c-32.576 18.688-51.2 53.76-51.2 91.2v152.064l400.32-233.92a32.448 32.448 0 0 0 16.256-28.032v-467.84l-130.304 74.88c-32.576 18.688-51.2 53.76-51.2 91.2v191.808c0 14.08-6.976 23.36-16.256 30.4" fill="#EE3306" p-id="8817"></path><path d="M701.952 101.888L534.4 3.648a39.552 39.552 0 0 0-32.576 0L101.568 237.568l130.304 74.88c32.64 18.688 72.128 18.688 102.4 0l167.552-98.304c2.368-2.304 4.672-2.304 7.04-2.304a32.832 32.832 0 0 1 25.6 2.304l167.488 98.24c32.64 18.752 72.192 18.752 102.4 0l130.368-74.88-232.768-135.616z" fill="#5AB200" p-id="8818"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,6 +1,8 @@
<svg width="126" height="45" viewBox="0 0 126 45" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.76597 0.337891H4.59152C1.87715 0.337891 0.5 1.14359 0.5 2.73083V42.0032C0.5 43.5914 1.87715 44.3961 4.59152 44.3961H6.76597C9.4814 44.3961 10.8575 43.5904 10.8575 42.0032V2.73083C10.8585 1.14359 9.4814 0.337891 6.76597 0.337891Z" fill="white"/>
<path d="M45.1179 39.5856C45.1179 34.9006 48.2073 30.9351 52.4743 29.5706C52.9617 27.3867 53.2075 24.978 53.2117 22.3445C53.2117 8.14862 45.9908 0.330078 32.878 0.330078H18.8996C16.9468 0.330078 16.0371 1.23137 16.0371 3.16736V41.5216C16.0371 43.4576 16.9468 44.3589 18.8985 44.3589H32.877C37.8761 44.3589 42.0159 43.2191 45.2282 41.0268C45.1578 40.5499 45.1211 40.0678 45.1169 39.5856M32.8759 35.5298H26.4398V9.15916H32.8759C40.9287 9.15916 42.6199 16.3296 42.6199 22.3445C42.6199 28.3594 40.9287 35.5298 32.8759 35.5298Z" fill="white"/>
<path d="M55.7368 34.7764C58.4165 34.7764 60.5889 36.9298 60.5889 39.5864C60.5889 42.243 58.4165 44.3964 55.7368 44.3964C53.0571 44.3964 50.8848 42.243 50.8848 39.5864C50.8848 36.9298 53.0571 34.7764 55.7368 34.7764Z" fill="#2EA76D"/>
<path d="M124.735 32.8363C124.593 32.7754 124.441 32.7417 124.286 32.7365C123.623 32.7144 123.171 32.9728 122.772 33.6126C122.536 33.996 122.303 34.3857 122.072 34.7754C121.192 36.2618 120.283 37.7965 118.962 38.8974C117.168 40.3912 114.57 41.0897 112.342 40.6842C111.017 40.4437 110.071 39.493 109.51 38.7388C108.482 37.3522 107.981 35.4855 108.061 33.3342C111.341 33.06 121.224 31.6114 122.01 24.1847C122.163 22.7446 121.749 21.4399 120.814 20.4104C119.629 19.1058 117.736 18.3862 115.487 18.3862C108.895 18.3862 102.389 25.2215 101.564 33.0138C101.338 35.1515 101.607 37.1253 102.364 38.8848C101.884 39.3449 101.335 39.7283 100.74 40.0224C100.187 40.283 99.7092 40.3365 99.3584 40.1769C98.9245 39.9773 98.7481 39.4741 98.6787 39.0886C98.4193 37.6621 98.7544 36.0223 99.1514 34.3279C99.3846 33.3342 99.6777 32.2995 99.9351 31.3856C100.732 28.5672 101.557 25.6533 101.282 22.7088C101.032 20.0134 99.1231 18.3389 96.3016 18.3389C92.3455 18.3389 89.7404 21.1374 88.0544 23.5366C88.0187 21.7487 87.5891 20.4504 86.7466 19.5827C85.9451 18.757 84.7676 18.3379 83.2486 18.3379C79.3682 18.3379 76.7956 21.026 75.1139 23.379C75.1359 23.1626 75.159 22.942 75.1832 22.7214C75.2893 21.713 75.3366 20.2676 74.5246 19.3747C74.0414 18.8432 73.3144 18.5732 72.3638 18.5732C71.7104 18.5532 71.057 18.6037 70.4152 18.7255C70.4057 18.7266 69.5339 18.8957 69.2019 19.1982C68.621 19.7266 68.8059 20.4556 68.912 20.8716C68.9256 20.9241 68.9382 20.9724 68.9445 21.0134C69.0107 21.4746 69.0307 21.941 69.0055 22.4063C68.8836 25.2362 68.3542 28.0651 67.851 30.4591C67.5789 31.7491 67.2733 33.0611 66.9707 34.3563C66.2985 37.2303 65.6051 40.2 65.249 43.1875C65.1703 43.7684 65.5757 44.3031 66.1566 44.3818C66.2092 44.3892 66.2627 44.3923 66.3163 44.3913L66.5253 44.3934C68.6578 44.4218 70.7534 44.3346 71.2461 43.1286C71.7913 41.7988 72.0928 40.1811 72.3596 38.7503L72.4772 38.1159C73.1096 34.8258 73.6621 32.4686 74.7756 29.4381C75.3492 27.876 76.3975 26.4695 77.2452 25.4169C78.2715 24.1427 79.3787 22.8958 80.6277 22.8643C81.1445 22.838 81.4817 22.9904 81.7359 23.3255C82.9492 24.9306 81.4387 30.1103 80.7937 32.3226C80.654 32.8006 80.5363 33.205 80.4617 33.5012L80.0174 35.2103C79.363 37.702 78.6865 40.2777 78.3398 42.8839C78.3052 43.1507 78.2726 43.4186 78.2453 43.6896L78.2159 44.053L78.489 44.261C79.0394 44.6844 82.9702 44.0919 83.0017 44.0825C84.4514 43.5971 84.7665 42.2452 84.8705 41.8009C85.1405 40.6517 85.3789 39.4773 85.609 38.3428L85.6258 38.2587C86.0586 36.1211 86.5061 33.9098 87.1752 31.7764C88.482 27.625 90.2236 24.7929 92.3539 23.358C93.2647 22.7425 94.2007 22.6742 94.624 23.1941C95.3604 24.0912 94.8939 26.5199 94.6944 27.5567C94.4191 28.9958 94.0662 30.4591 93.7258 31.8751L93.708 31.9476C93.4895 32.8499 93.2731 33.7512 93.0714 34.6557C92.4485 37.4583 91.9369 40.9332 93.5284 42.9385C94.3383 43.9606 95.5914 44.4785 97.2533 44.4785C99.0159 44.4785 100.674 43.8955 102.471 42.6444C102.966 42.2967 103.466 41.8923 104.05 41.4111C106.073 43.6906 108.37 44.6676 111.687 44.6676C119.185 44.6676 122.71 39.7283 124.71 36.0129C124.976 35.537 125.211 35.0443 125.412 34.538C125.66 33.8542 125.362 33.1062 124.734 32.8373M115.539 23.4557C115.549 23.5713 115.559 23.6868 115.56 23.8034C115.56 23.9778 115.551 24.1522 115.533 24.3265C115.477 24.9043 115.363 25.4757 115.194 26.0314C114.124 29.4717 111.112 30.0809 108.506 30.1681C108.849 28.6996 109.358 27.2741 110.021 25.919C111.288 23.358 112.881 21.7676 114.175 21.7666C114.295 21.7666 114.414 21.7844 114.528 21.817C114.588 21.838 114.646 21.8632 114.701 21.8937L114.756 21.9178C114.778 21.9262 114.799 21.9368 114.819 21.9494C114.876 21.9872 114.928 22.0313 114.977 22.0786L115.021 22.1195C115.039 22.1342 115.054 22.15 115.07 22.1668C115.105 22.2078 115.137 22.2519 115.166 22.2981L115.204 22.3559C115.233 22.3958 115.259 22.4378 115.282 22.4809C115.296 22.5082 115.307 22.5387 115.342 22.6185C115.379 22.7036 115.41 22.7908 115.438 22.879L115.462 22.9862C115.491 23.0986 115.513 23.212 115.528 23.3265L115.539 23.4557Z" fill="white"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg">
<ellipse style="" cx="90" cy="90" rx="90" ry="90" transform="matrix(1, 0, 0, 1, 0, -1.7763568394002505e-15)"/>
<path d="M 37.753 62.604 L 35.578 62.604 C 32.864 62.604 31.487 63.41 31.487 64.997 L 31.487 104.269 C 31.487 105.858 32.864 106.662 35.578 106.662 L 37.753 106.662 C 40.468 106.662 41.844 105.857 41.844 104.269 L 41.844 64.997 C 41.845 63.41 40.468 62.604 37.753 62.604 Z" fill="white" style="transform-origin: 90px 90px;"/>
<path d="M 76.105 101.852 C 76.105 97.167 79.194 93.201 83.461 91.837 C 83.949 89.653 84.194 87.244 84.199 84.611 C 84.199 70.415 76.978 62.596 63.865 62.596 L 49.886 62.596 C 47.934 62.596 47.024 63.498 47.024 65.434 L 47.024 103.788 C 47.024 105.724 47.934 106.625 49.885 106.625 L 63.864 106.625 C 68.863 106.625 73.003 105.485 76.215 103.293 C 76.145 102.816 76.108 102.334 76.104 101.852 M 63.863 97.796 L 57.427 97.796 L 57.427 71.425 L 63.863 71.425 C 71.916 71.425 73.607 78.596 73.607 84.611 C 73.607 90.626 71.916 97.796 63.863 97.796 Z" fill="white" style="transform-origin: 90px 90px;"/>
<path d="M 86.724 97.043 C 89.403 97.043 91.576 99.196 91.576 101.853 C 91.576 104.509 89.403 106.663 86.724 106.663 C 84.044 106.663 81.872 104.509 81.872 101.853 C 81.872 99.196 84.044 97.043 86.724 97.043 Z" fill="#2EA76D" style="transform-origin: 90px 90px;"/>
<path d="M 155.722 95.102 C 155.58 95.042 155.428 95.008 155.273 95.003 C 154.61 94.981 154.158 95.239 153.759 95.879 C 153.523 96.262 153.29 96.652 153.059 97.042 C 152.179 98.528 151.27 100.063 149.949 101.164 C 148.155 102.657 145.557 103.356 143.329 102.95 C 142.004 102.71 141.058 101.759 140.497 101.005 C 139.469 99.618 138.968 97.752 139.048 95.6 C 142.328 95.326 152.211 93.878 152.997 86.451 C 153.15 85.011 152.736 83.706 151.801 82.677 C 150.616 81.372 148.723 80.652 146.474 80.652 C 139.882 80.652 133.376 87.488 132.551 95.28 C 132.325 97.418 132.594 99.391 133.351 101.151 C 132.871 101.611 132.322 101.994 131.727 102.289 C 131.174 102.549 130.696 102.603 130.345 102.443 C 129.911 102.243 129.735 101.74 129.666 101.355 C 129.406 99.928 129.741 98.288 130.138 96.594 C 130.371 95.6 130.665 94.566 130.922 93.652 C 131.719 90.833 132.544 87.919 132.269 84.975 C 132.019 82.28 130.11 80.605 127.288 80.605 C 123.332 80.605 120.727 83.404 119.041 85.803 C 119.006 84.015 118.576 82.717 117.733 81.849 C 116.932 81.023 115.754 80.604 114.235 80.604 C 110.355 80.604 107.782 83.292 106.101 85.645 C 106.123 85.429 106.146 85.208 106.17 84.988 C 106.276 83.979 106.323 82.534 105.511 81.641 C 105.028 81.109 104.301 80.839 103.351 80.839 C 102.697 80.819 102.044 80.87 101.402 80.992 C 101.393 80.993 100.521 81.162 100.189 81.464 C 99.608 81.993 99.793 82.722 99.899 83.138 C 99.912 83.19 99.925 83.239 99.931 83.28 C 99.998 83.741 100.018 84.207 99.992 84.672 C 99.87 87.502 99.341 90.331 98.838 92.725 C 98.566 94.015 98.26 95.327 97.958 96.622 C 97.285 99.496 96.592 102.466 96.236 105.454 C 96.157 106.035 96.563 106.569 97.143 106.648 C 97.196 106.655 97.25 106.658 97.303 106.657 L 97.512 106.66 C 99.645 106.688 101.74 106.601 102.233 105.395 C 102.778 104.065 103.08 102.447 103.346 101.016 L 103.464 100.382 C 104.096 97.092 104.649 94.735 105.762 91.704 C 106.336 90.142 107.384 88.736 108.232 87.683 C 109.258 86.409 110.366 85.162 111.615 85.13 C 112.131 85.104 112.469 85.257 112.723 85.592 C 113.936 87.197 112.426 92.376 111.781 94.589 C 111.641 95.067 111.523 95.471 111.449 95.767 L 111.004 97.476 C 110.35 99.968 109.673 102.544 109.327 105.15 C 109.292 105.417 109.259 105.685 109.232 105.956 L 109.203 106.319 L 109.476 106.527 C 110.026 106.951 113.957 106.358 113.989 106.349 C 115.438 105.863 115.753 104.511 115.857 104.067 C 116.127 102.918 116.366 101.743 116.596 100.609 L 116.613 100.525 C 117.045 98.387 117.493 96.176 118.162 94.043 C 119.469 89.891 121.21 87.059 123.341 85.624 C 124.252 85.009 125.188 84.94 125.611 85.46 C 126.347 86.357 125.881 88.786 125.681 89.823 C 125.406 91.262 125.053 92.725 124.713 94.141 L 124.695 94.214 C 124.476 95.116 124.26 96.017 124.058 96.922 C 123.435 99.724 122.924 103.199 124.515 105.205 C 125.325 106.227 126.578 106.745 128.24 106.745 C 130.003 106.745 131.661 106.162 133.458 104.911 C 133.953 104.563 134.453 104.158 135.037 103.677 C 137.06 105.957 139.357 106.934 142.674 106.934 C 150.172 106.934 153.697 101.994 155.697 98.279 C 155.963 97.803 156.198 97.31 156.399 96.804 C 156.647 96.12 156.349 95.372 155.721 95.103 M 146.526 85.722 C 146.536 85.837 146.546 85.953 146.547 86.07 C 146.547 86.244 146.538 86.418 146.52 86.593 C 146.464 87.17 146.35 87.742 146.181 88.298 C 145.111 91.738 142.099 92.347 139.493 92.434 C 139.836 90.966 140.345 89.54 141.008 88.185 C 142.275 85.624 143.868 84.034 145.162 84.033 C 145.282 84.033 145.401 84.051 145.515 84.083 C 145.575 84.104 145.633 84.129 145.688 84.16 L 145.743 84.184 C 145.765 84.192 145.786 84.203 145.806 84.216 C 145.863 84.253 145.915 84.297 145.964 84.345 L 146.008 84.386 C 146.026 84.4 146.041 84.416 146.057 84.433 C 146.092 84.474 146.124 84.518 146.153 84.564 L 146.191 84.622 C 146.22 84.662 146.246 84.704 146.269 84.747 C 146.283 84.774 146.294 84.805 146.329 84.885 C 146.366 84.97 146.397 85.057 146.425 85.145 L 146.449 85.252 C 146.478 85.365 146.5 85.478 146.515 85.593 L 146.526 85.722 Z" fill="white" style="transform-origin: 90px 90px;"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340558126" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16285" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M891.318857 340.845714c4.900571 0 9.728 0.292571 14.628572 0.804572a409.965714 409.965714 0 0 1 108.836571 30.061714c10.093714 4.534857 12.580571 8.192 3.949714 17.334857-24.868571 26.624-45.494857 57.051429-61.001143 89.965714-16.822857 35.328-35.108571 69.851429-52.297142 105.033143a225.28 225.28 0 0 1-52.150858 69.412572c-53.613714 48.493714-116.150857 68.973714-187.538285 59.099428-81.92-11.337143-159.451429-38.985143-232.740572-75.483428a143.506286 143.506286 0 0 1-10.459428-5.485715 5.339429 5.339429 0 0 1 0.292571-9.216l5.12-2.706285c59.245714-31.670857 108.836571-75.849143 156.525714-122.294857 20.187429-19.529143 39.497143-40.009143 59.904-59.318858A345.014857 345.014857 0 0 1 804.571429 352.256c13.165714-3.218286 26.550857-5.778286 39.789714-8.630857h0.585143l28.233143-2.56" fill="#133C9A" p-id="16286"></path><path d="M317.659429 913.846857c-8.996571-0.512-31.158857-3.584-33.865143-3.949714a536.429714 536.429714 0 0 1-165.083429-48.274286c-30.208-14.116571-59.245714-30.72-88.356571-46.957714-19.163429-10.678857-27.794286-27.282286-27.648-49.883429 0.585143-83.382857 0.585143-166.765714 0-250.148571C2.413714 461.019429 0.731429 407.405714 0 353.718857c0-4.754286 0.731429-9.508571 2.194286-13.897143 3.291429-9.728 9.947429-10.24 16.530285-3.949714 7.606857 7.314286 13.677714 16.237714 21.211429 23.405714 67.291429 66.413714 138.752 127.195429 218.770286 177.225143 45.056 28.891429 91.940571 54.710857 140.434285 77.385143 77.750857 35.328 157.549714 66.486857 241.078858 86.235429 73.874286 17.481143 145.627429 6.436571 205.458285-40.374858 18.285714-15.652571 27.282286-27.062857 48.932572-55.881142a359.862857 359.862857 0 0 1-37.376 72.850285c-13.897143 21.942857-45.348571 51.2-69.193143 74.093715-36.278857 35.108571-83.748571 63.561143-128.292572 87.552-48.566857 26.185143-99.035429 47.104-152.941714 58.514285-27.648 6.948571-67.584 14.848-81.334857 15.579429-2.413714-0.146286-10.678857 1.682286-14.848 1.389714-35.547429 2.633143-57.490286 3.657143-92.891429 0z" fill="#3370FF" p-id="16287"></path><path d="M165.083429 110.518857a52.443429 52.443429 0 0 1 7.460571 0c152.649143 0 304.128 2.486857 456.630857 2.486857 0.292571 0 0.585143 0 0.731429 0.219429 14.189714 12.361143 27.282286 25.746286 39.277714 40.155428 34.450286 34.230857 60.123429 93.622857 77.677714 129.755429 8.777143 25.014857 21.942857 48.859429 28.16 76.8v0.438857c-15.579429 5.046857-30.72 11.190857-45.348571 18.505143-44.178286 22.381714-64.219429 38.765714-100.790857 74.752-19.968 19.529143-37.010286 37.083429-63.488 62.098286a563.346286 563.346286 0 0 1-29.769143 26.916571c-7.021714-12.434286-125.732571-244.589714-364.251429-427.300571" fill="#00D6B9" p-id="16288"></path></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340195618" class="icon" viewBox="0 0 1050 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6355" xmlns:xlink="http://www.w3.org/1999/xlink" width="205.078125" height="200"><path d="M681.80215 142.259694a100.529011 100.529011 0 0 1-66.041812 37.537087 1221.89083 1221.89083 0 0 1-206.102068 5.630563l-4.486854-3.372473V0c-37.537087 37.537087-82.962827 37.537087-129.884186 41.672032v143.69666H128.130119A120.52924 120.52924 0 0 0 2.322226 289.416805a211.439372 211.439372 0 0 0-2.228765 37.537087v581.062375a119.708116 119.708116 0 0 1 75.074174-37.537087 428.157397 428.157397 0 0 1 57.801249-4.516181h425.224812a119.356206 119.356206 0 0 0 119.004296-97.948336 231.204995 231.204995 0 0 0 3.372473-42.434504V156.570709z m-203.814651 675.667564H130.388209V309.680967a64.516868 64.516868 0 0 1 72.816084-72.816084h72.845409v265.369609H221.972836a70.557993 70.557993 0 0 0-75.044848 63.431812 239.328255 239.328255 0 0 1 128.359242-10.87989v212.084541c0 18.768543 3.753709 22.522252 22.141016 22.522252h85.220917c18.768543 0 22.522252-3.372473 22.522253-21.75978V569.801249c0-13.13798 4.134945-17.272925 16.891689-16.510453a301.235122 301.235122 0 0 0 48.798213 0 70.557993 70.557993 0 0 0 64.92743-62.698666c-40.90956 23.284724-85.044962 7.888653-129.033737 13.519217V241.351738h144.517785v504.873819a65.308666 65.308666 0 0 1-73.314623 71.320465z m572.440575-299.534223v-16.891689h-67.449453a93.842717 93.842717 0 0 0 66.83361-90.910132 201.996449 201.996449 0 0 0 0-20.528095V103.608225a127.156882 127.156882 0 0 1-70.206083 33.783378 581.267656 581.267656 0 0 1-67.18552 7.888654h-60.059339a121.966207 121.966207 0 0 0-128.623174 131.526433v747.19331c27.038433-34.89776 64.92743-34.135288 102.464517-37.537087v-130.617332h88.974626a124.282949 124.282949 0 0 0 134.898906-135.133513c0.762472-67.449453 0.381236-134.898906 0.381236-202.348359z m-103.608225 216.19016a64.194284 64.194284 0 0 1-70.587319 70.587319h-48.387651V270.267026a64.516868 64.516868 0 0 1 75.074174-75.074174h44.663268v276.278824c-75.074174 7.126181-94.223953 20.528094-101.731371 61.584284 15.777307-2.932585 31.906524-7.126181 48.416977-8.6218s34.54585 0 53.69563 0v17.59551z m0 0" p-id="6356" fill="#d81e06"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340610287" class="icon" viewBox="0 0 1653 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17270" xmlns:xlink="http://www.w3.org/1999/xlink" width="322.8515625" height="200"><path d="M344.8620198 721.82988526a57.857089 57.857089 0 0 1-46.13274501-56.07295017v-308.4012244a59.89610558 59.89610558 0 0 1 46.13274501-56.07295017l286.35436058-62.06256065 30.07549089-122.72329718H328.80476645A210.78331632 210.78331632 0 0 0 116.61962599 327.28021902v364.47417458a213.71440233 213.71440233 0 0 0 212.18514046 212.31257895h332.48710482l-30.07549089-122.21354321zM1178.05508073 116.49690269H843.01920461l30.58524561 122.72329718 286.35436059 62.06256065a57.98452749 57.98452749 0 0 1 46.132745 56.07295017v308.4012244a60.15098257 60.15098257 0 0 1-46.13274502 56.07295017l-286.35436057 62.06256066-30.58524561 122.72329716H1178.05508073a212.44001744 212.44001744 0 0 0 212.94977139-212.82233291V327.28021902A213.33208686 213.33208686 0 0 0 1178.05508073 116.49690269z" fill="#F76E05" p-id="17271"></path><path d="M631.21638038 495.49906876h244.29964793v30.07549166H631.21638038z" fill="#F76E05" p-id="17272"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -2,13 +2,9 @@
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="katman_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 600" style="enable-background:new 0 0 800 600;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0052FF;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M399.8,69.1L399.8,69.1c127.3,0,230.5,103.2,230.5,230.5l0,0c0,127.3-103.2,230.5-230.5,230.5l0,0
c-127.3,0-230.5-103.2-230.5-230.5l0,0C169.3,172.3,272.5,69.1,399.8,69.1z"/>
<path class="st1" d="M399.9,380.6c-44.8,0-81-36.3-81-81s36.3-81,81-81c40.1,0,73.4,29.2,79.8,67.5h81.6
<path d="M399.8,69.1L399.8,69.1c127.3,0,230.5,103.2,230.5,230.5l0,0c0,127.3-103.2,230.5-230.5,230.5l0,0
c-127.3,0-230.5-103.2-230.5-230.5l0,0C169.3,172.3,272.5,69.1,399.8,69.1z" style="fill:#0052FF;"/>
<path d="M399.9,380.6c-44.8,0-81-36.3-81-81s36.3-81,81-81c40.1,0,73.4,29.2,79.8,67.5h81.6
c-6.9-83.2-76.5-148.6-161.5-148.6c-89.5,0-162.1,72.6-162.1,162.1s72.6,162.1,162.1,162.1c85,0,154.6-65.4,161.5-148.6h-81.7
C473.2,351.4,440,380.6,399.9,380.6z"/>
C473.2,351.4,440,380.6,399.9,380.6z" style="fill:#FFFFFF;"/>
</svg>

Before

Width:  |  Height:  |  Size: 904 B

After

Width:  |  Height:  |  Size: 845 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -1 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 400 400"><path fill="#150A45" d="M0 0h400v400H0z"/><path fill="#fff" d="M234.117 91.106C225.896 77.188 211.92 69 192.19 69 155.196 69 133 98.475 133 139.413c0 40.937 22.196 70.412 59.19 70.412 6.577 0 13.976-.819 19.73-3.275 6.577-2.456 12.332-6.55 16.442-11.463v19.65c0 13.1-7.399 29.475-29.595 29.475-17.264 0-25.485-9.825-28.773-19.65L139.577 239.3c8.221 18.012 26.306 34.388 61.656 34.388 51.792 0 65.767-35.207 65.767-65.5V70.638h-32.061l-.822 20.468Zm-33.706 86.788c-18.908 0-29.595-14.738-29.595-38.481 0-23.744 10.687-38.482 29.595-38.482s29.595 14.738 29.595 38.482c0 22.925-10.687 38.481-29.595 38.481ZM267 284.332V331H133.822v-27.837h106.049v-18.831H267Z"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M 399.262 200.003 C 399.262 255.201 376.96 305.199 340.838 341.349 C 304.762 377.548 254.87 399.898 199.787 399.898 C 144.704 399.898 94.813 377.549 58.737 341.35 C 22.615 305.2 0.312 255.201 0.312 200.003 C 0.312 144.805 22.614 94.807 58.736 58.657 C 94.812 22.458 144.704 0.10800000000000001 199.787 0.10800000000000001 C 254.87 0.10800000000000001 304.762 22.458 340.838 58.657 C 376.96 94.807 399.262 144.805 399.262 200.003" style="fill: rgb(21, 10, 69);" transform="matrix(1, 0, 0, 1, 0, -3.552713678800501e-15)"/>
<path fill="#fff" d="M234.117 91.106C225.896 77.188 211.92 69 192.19 69 155.196 69 133 98.475 133 139.413c0 40.937 22.196 70.412 59.19 70.412 6.577 0 13.976-.819 19.73-3.275 6.577-2.456 12.332-6.55 16.442-11.463v19.65c0 13.1-7.399 29.475-29.595 29.475-17.264 0-25.485-9.825-28.773-19.65L139.577 239.3c8.221 18.012 26.306 34.388 61.656 34.388 51.792 0 65.767-35.207 65.767-65.5V70.638h-32.061l-.822 20.468Zm-33.706 86.788c-18.908 0-29.595-14.738-29.595-38.481 0-23.744 10.687-38.482 29.595-38.482s29.595 14.738 29.595 38.482c0 22.925-10.687 38.481-29.595 38.481ZM267 284.332V331H133.822v-27.837h106.049v-18.831H267Z" style="" transform="matrix(1, 0, 0, 1, 0, -3.552713678800501e-15)"/>
</svg>

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,9 +1,5 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 333.8 127" style="enable-background:new 0 0 333.8 127;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F45D48;}
</style>
<g>
<path class="st0" d="M296.4,18.6c-20.6,0-37.4,16.8-37.4,37.6c0,20.7,16.8,37.6,37.4,37.6c20.6,0,37.4-16.9,37.4-37.6
<path d="M296.4,18.6c-20.6,0-37.4,16.8-37.4,37.6c0,20.7,16.8,37.6,37.4,37.6c20.6,0,37.4-16.9,37.4-37.6
C333.8,35.4,317,18.6,296.4,18.6L296.4,18.6z M296.4,75.9c-10.9,0-19.7-8.9-19.7-19.8c0-10.9,8.8-19.8,19.7-19.8
c10.8,0,19.7,8.9,19.7,19.8C316.1,67,307.2,75.9,296.4,75.9L296.4,75.9z M186.2,48.5l-6.5-3.3c-2.8-1.4-4.6-2.5-5.3-3.3
c-0.7-0.7-1.1-1.7-1.1-2.6c0-1.3,0.6-2.3,1.7-3.2c1.1-0.9,2.7-1.3,4.7-1.3c3.7,0,7.7,2.2,12.2,6.7l11-11.1
@@ -17,7 +13,6 @@
c0,5.1,0,13.8-3.7,17.6c-1.8,1.8-3.7,3.4-7.8,3.4c-4.1,0-6.1-1.6-7.9-3.4c-3.7-3.7-3.7-12.5-3.7-17.6V20H87.2v35.6
c-0.1,7.4-0.1,21,8.8,30c5.2,5.3,11.5,8,20.5,8c9,0,15.3-2.7,20.5-8c8.9-9,8.9-22.7,8.8-30L145.9,20z M247,72.7
c-1.4,1.1-4.9,3.5-8.8,3c-3.2-0.4-5.8-2.8-6.2-10.7V35.3h21V20h-21V0h-17.8v3.9h0v58.7c0,9.3,2.3,31,24,31
c10.9-0.2,17.6-6.1,20.4-8.5l0.4-0.3l-10.7-13.2C248.2,71.8,247.5,72.4,247,72.7L247,72.7z M247,72.7">
c10.9-0.2,17.6-6.1,20.4-8.5l0.4-0.3l-10.7-13.2C248.2,71.8,247.5,72.4,247,72.7L247,72.7z M247,72.7" style="fill:#F45D48;">
</path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 90"><path fill="#FFF" d="M0 0h90v90H0z"/><path fill="#FFF" d="M33.258 25.45h26.027v33.51H33.258z"/><path d="m39.22 53.522 2.194-12.578a6.684 6.684 0 0 1-2.21-7.444 6.645 6.645 0 0 1 6.311-4.495v-13.96H28.567c-3.627 0-6.567 2.952-6.567 6.593v32.324c-.005.61.13 1.213.394 1.762C23.816 58.61 29.43 67.876 45.5 75V54.038a36.635 36.635 0 0 1-6.28-.516Z" fill="#E21D3E"/><path d="M62.417 15H45.5v13.96a6.644 6.644 0 0 1 6.302 4.458 6.684 6.684 0 0 1-2.14 7.435l2.193 12.638c-2.098.367-4.225.55-6.355.547V74.97c16.055-7.094 21.684-16.39 23.106-19.276.264-.55.399-1.153.394-1.762v-32.31a6.606 6.606 0 0 0-1.918-4.686A6.555 6.555 0 0 0 62.417 15Z" fill="#B51E23"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg">
<path fill="#FFF" d="M33.258 25.45h26.027v33.51H33.258z"/>
<path d="m39.22 53.522 2.194-12.578a6.684 6.684 0 0 1-2.21-7.444 6.645 6.645 0 0 1 6.311-4.495v-13.96H28.567c-3.627 0-6.567 2.952-6.567 6.593v32.324c-.005.61.13 1.213.394 1.762C23.816 58.61 29.43 67.876 45.5 75V54.038a36.635 36.635 0 0 1-6.28-.516Z" fill="#E21D3E"/>
<path d="M62.417 15H45.5v13.96a6.644 6.644 0 0 1 6.302 4.458 6.684 6.684 0 0 1-2.14 7.435l2.193 12.638c-2.098.367-4.225.55-6.355.547V74.97c16.055-7.094 21.684-16.39 23.106-19.276.264-.55.399-1.153.394-1.762v-32.31a6.606 6.606 0 0 0-1.918-4.686A6.555 6.555 0 0 0 62.417 15Z" fill="#B51E23"/>
</svg>

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 729 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 26.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 160.5 95.1" style="enable-background:new 0 0 160.5 95.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M152,47.7c2.3-2.3,4.5-5,5.9-8.1c8-18.1-3.6-37.8-23.4-38.5h-51v19.7h48.4c5,0,8.7,3.6,8.8,8.3 c0.1,4.9-3.1,8.3-8.3,8.7c-1,0.1-48.8,0-48.8,0v56.3h51c19.8-0.7,31.4-20.4,23.4-38.5C156.6,52.7,154.4,50,152,47.7z M131.9,74.5 h-28.5v-17c13.3,0,28.5,0,29,0c5.2,0.4,8.5,3.8,8.3,8.7C140.5,70.9,136.9,74.5,131.9,74.5z"/>
<path class="st0" d="M20.8,67.3V94H1.3V64c0.3-15,10.2-25.2,25.3-26.1c7.6-0.4,15.2-0.1,22.8-0.2c4.4-0.1,7.7-2.3,8.7-5.8 c1-3.7,0.1-6.9-2.9-9.4c-1.6-1.3-3.5-1.9-5.6-1.8H29V1.1h19.2c4.3,0,6.1,0.4,8.4,0.9c13.7,2.7,21.6,13.3,21.3,28.3 c-0.3,14.1-9.2,24.4-22.8,26.3c-8.2,1.2-16.4,0.4-24.7,0.6c-6.2,0.1-9.6,3-9.6,9.3L20.8,67.3z"/>
<rect x="1.2" y="1.3" class="st0" width="19.5" height="19.5"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340476837" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12844" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1019.830857 176.274286c-4.242286-4.169143-8.484571-4.169143-12.726857-4.169143-12.8 4.242286-165.741714 259.145143-497.152 250.660571-55.222857 0-114.761143-4.242286-169.984-21.211428L314.587429 312.32s-4.242286-21.211429-25.526858-34.011429c-16.969143-8.484571-25.453714-8.484571-29.696-4.242285v4.242285l12.726858 101.961143C106.276571 308.077714 21.284571 176.347429 12.8 172.105143c-4.242286 0-8.484571 0-12.726857 4.242286v12.726857a519.314286 519.314286 0 0 0 280.429714 310.125714l38.253714 242.249143c4.242286 68.022857 50.980571 110.445714 110.445715 110.445714h182.710857c59.465143 0 106.203429-42.422857 110.445714-110.445714l34.011429-199.68v-4.242286s-16.969143 0-50.980572 21.211429c-34.011429 25.526857-42.422857 59.465143-42.422857 59.465143s-34.011429 84.992-42.569143 119.003428c-8.484571 38.253714-50.980571 34.011429-50.980571 34.011429H467.456c-16.969143 0-34.011429-12.8-34.011429-29.769143l-59.465142-212.48c42.422857 12.8 89.234286 17.042286 140.214857 17.042286 237.933714 0 437.613714-144.457143 509.878857-356.937143-4.242286 0-4.242286-8.484571-4.242286-12.726857" fill="#02A7E0" p-id="12845"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 343 358" style="enable-background:new 0 0 343 358;" xml:space="preserve">
<style type="text/css">
.st0{fill:#D64309;}
</style>
<path class="st0" d="M171.3,102.6c0,0-69-2.1-69,52.4c0,54.5,32.8,99.8,69,99.8c36.2,0,69-45.4,69-99.8
C240.3,100.5,171.3,102.6,171.3,102.6z M154.6,171.1c-1.7,3.7-5.1,5.6-9.9,5.6c-4.9,0-8.3-1.9-9.9-5.6c-0.7-1.5-1-3.2-1-5.4
c0-2.3,0.3-3.9,1-5.5c1.7-3.7,5-5.5,9.9-5.5c4.8,0,8.2,1.8,9.9,5.5c0.7,1.6,1,3.2,1,5.5C155.6,167.9,155.3,169.6,154.6,171.1z
M214.1,152.1c-4.3-0.6-17.1-0.7-23.9,5.3c-3.4,3-5.1,7.4-5.1,13.3v40.2h-15.4v-40.2c0-10.4,3.6-19,10.4-24.9
c13.3-11.6,33.7-9.2,36-8.9L214.1,152.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 906 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 90"><path fill="#FF5900" fill-rule="nonzero" d="m76.14 69.42-1.43.92a53.07 53.07 0 0 1-60.03-.06l-1.42-.92L8 78.34l1.24.8a63.44 63.44 0 0 0 70.98 0l1.23-.8-5.31-8.92Zm-54.1-8.74L57.9 0H71.3l-35.8 60.68H22.04ZM36.63 5.23A15.12 15.12 0 0 0 25.75.73c-4.27 0-7.98 1.49-10.95 4.44a14.73 14.73 0 0 0-4.45 10.9c0 4.3 1.48 7.93 4.45 10.89 2.85 2.89 6.8 4.55 10.95 4.43 4.2 0 7.85-1.54 10.88-4.5a14.99 14.99 0 0 0 4.51-10.83c.06-4.07-1.57-8-4.51-10.83Zm-6.56 15.14a5.58 5.58 0 0 1-4.26 1.79 6.01 6.01 0 0 1-4.4-1.79 5.59 5.59 0 0 1-1.79-4.3c0-1.73.62-3.15 1.8-4.32a5.9 5.9 0 0 1 4.39-1.78 6 6 0 0 1 4.33 1.78 6.02 6.02 0 0 1-.07 8.62Zm48.42 15.2a15 15 0 0 0-10.89-4.5c-4.26 0-7.97 1.49-10.94 4.44a14.73 14.73 0 0 0-4.45 10.83c0 4.3 1.48 7.94 4.45 10.9 2.84 2.89 6.8 4.55 10.94 4.42 4.2 0 7.86-1.53 10.89-4.49A14.99 14.99 0 0 0 83 46.34c0-4.06-1.6-8-4.51-10.77Zm-6.56 15.14a6.01 6.01 0 0 1-4.33 1.79 6.01 6.01 0 0 1-6.12-6.16c0-1.72.62-3.14 1.8-4.3a5.9 5.9 0 0 1 4.39-1.8 6 6 0 0 1 4.32 1.8 5.95 5.95 0 0 1-.06 8.67Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +1,17 @@
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="M0 0h90v90H0z" fill="#E20074"/><g fill="#FFF"><path d="M18.692 55.385V42.404h12.981v12.98zm39.635 0V42.404h12.981v12.98z"/><path d="M70.615 12.98h-51.23l-.693 22.674 3.462.52c.692-6.75 2.423-11.597 5.192-14.886 2.942-3.288 7.096-5.192 12.462-5.365v47.25c0 4.154-.52 6.75-1.731 7.962-1.039 1.038-2.77 1.73-5.192 1.903-.693 0-1.904.174-3.635.174v3.634h31.673v-3.634c-1.73 0-2.942 0-3.635-.174-2.423-.173-4.153-.865-5.192-1.903-1.211-1.212-1.73-3.981-1.73-7.962V16.096c5.365.173 9.519 1.904 12.46 5.366 2.943 3.288 4.674 8.134 5.193 14.884l3.462-.52-.866-22.845Z"/></g></g></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 720 720" style="enable-background:new 0 0 720 720;" xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">
.st0{fill:#E20074;}
</style>
</defs>
<g>
<g>
<g>
<polygon class="st0" points="96.62,469.28 223.57,469.28 223.57,342.31 96.62,342.31 96.62,469.28 &#9;&#9;&#9;"/>
<path class="st0" d="M402.16,82.88c103.43,1.82,165.08,70.76,174.17,196.81l33.57-5.44l-6.41-221.3H102.88l-6.31,221.3&#10;&#9;&#9;&#9;&#9;l33.53,5.44c9.09-126.05,69.86-194.99,174.17-196.81v463.44c0,84.34-14.53,97.97-105.21,98.87v35.35h308.34v-35.35&#10;&#9;&#9;&#9;&#9;c-90.68-0.9-105.23-14.53-105.23-98.87V82.88L402.16,82.88z"/>
<polygon class="st0" points="481.85,469.28 608.78,469.28 608.78,342.31 481.85,342.31 481.85,469.28 &#9;&#9;&#9;"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 660 B

After

Width:  |  Height:  |  Size: 858 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340512759" class="icon" viewBox="0 0 1402 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13871" xmlns:xlink="http://www.w3.org/1999/xlink" width="273.828125" height="200"><path d="M1215.068154 831.197568a199.23384 199.23384 0 0 1-148.202014 58.441927l-477.741777 1.258319c148.202014-142.329859 263.967361-265.64512 276.830178-271.796902a660.058216 660.058216 0 0 1 64.453895-58.302113c51.311452-58.302113 96.471122-64.873335 141.910419-65.013148a190.006167 190.006167 0 0 1 142.190046 57.882674c77.596338 70.885303 77.875964 206.364314 0 277.529243z m95.911869-368.128211c-58.302113-57.882673-142.329859-102.902531-226.217791-102.622904S936.979657 393.162747 878.258104 432.310449c-19.294224 19.573851-57.882673 45.439297-83.887932 83.887932-32.017228 19.294224-508.360872 504.725728-508.360872 504.725728l703.679942-1.398132a520.384809 520.384809 0 0 0 109.613565-6.711035 372.322608 372.322608 0 0 0 206.364314-91.15822c122.336568-129.467043 121.777315-335.55173 5.312902-458.307738z" fill="#00A3FF" p-id="13872"></path><path d="M517.539994 432.310449a322.688914 322.688914 0 0 0-200.212532-64.034456 289.553181 289.553181 0 0 0-226.497418 104.440477A333.174906 333.174906 0 0 0 98.100331 937.455616q77.596338 77.316711 174.4869 77.037085l128.767977-123.175448h-70.605677A264.386801 264.386801 0 0 1 181.988264 833.854019c-77.596338-77.176898-77.875964-199.793093 0-283.960651a180.638682 180.638682 0 0 1 141.211353-58.441927c38.868075 0 77.456524 6.291595 129.327229 57.882674 19.573851 25.585819 77.596338 64.314082 97.030376 90.039714h6.431408l77.316711-90.598967c-25.725633-32.57648-90.598967-83.608306-115.765347-116.464413" fill="#00C8DC" p-id="13873"></path><path d="M1103.916643 282.850115C1045.334904 115.214063 877.279412-1.110536 696.500917 0.007969 476.99416 0.567222 303.206326 162.470932 265.037317 368.97506c12.862816 0 32.157041-6.431408 51.591079-6.431409s51.591079 6.291595 71.025116 6.151782A303.39469 303.39469 0 0 1 683.917727 129.055572 313.601055 313.601055 0 0 1 968.297819 308.995188s6.571221 6.431408 6.431408 0c45.299484-6.431408 90.459154-26.005259 129.187416-26.145073" fill="#006EFF" p-id="13874"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,11 @@
<svg width="1606" height="1005.0000000000001" xmlns="http://www.w3.org/2000/svg" class="icon">
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="1007" width="1608" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<path id="svg_4" class="selected" fill="#F3A22F" d="m1332.2,333.8c-12.8,-108.8 -108.8,-185.6 -217.6,-185.6c-25.6,0 -57.6,6.4 -83.2,12.8c-70.4,-83.2 -179.2,-134.4 -288,-134.4c-147.2,0 -275.2,83.2 -339.2,211.2l-19.2,0c-198.4,0 -358.4,153.6 -364.8,352s153.6,358.4 352,364.8l467.2,0c38.4,0 70.4,-32 70.4,-70.4c0,-38.4 -32,-70.4 -70.4,-70.4l-435.2,0l-6.4,0c-115.2,0 -211.2,-89.6 -211.2,-204.8c0,-108.8 83.2,-198.4 192,-211.2c19.2,0 44.8,0 64,6.4l6.4,0l44.8,12.8c12.8,-128 121.6,-230.4 256,-230.4c89.6,0 172.8,51.2 217.6,128c6.4,12.8 6.4,19.2 12.8,32l12.8,-12.8c32,-25.6 76.8,-32 115.2,-25.6l0,-6.4c64,6.4 108.8,57.6 108.8,121.6c0,19.2 -6.4,38.4 -12.8,57.6c19.2,12.8 32,25.6 57.6,32c12.8,-12.8 25.6,-19.2 32,-32c102.4,6.4 179.2,96 172.8,198.4c-6.4,96 -89.6,172.8 -192,172.8c-76.8,0 -153.6,-51.2 -179.2,-128l76.8,0c12.8,0 19.2,-6.4 19.2,-19.2c0,-6.4 0,-6.4 -6.4,-12.8l-153.6,-204.8c-6.4,-6.4 -19.2,-12.8 -32,-6.4l-6.4,6.4l-153.6,204.8c-6.4,6.4 -6.4,25.6 6.4,32c6.4,0 6.4,6.4 12.8,6.4l89.6,0c32,179.2 204.8,300.8 384,268.8s300.8,-204.8 268.8,-384c-25.6,-153.6 -134.4,-256 -268.8,-281.6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1727340360476" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9874" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M836.395 475.861L709.973 970.155a8.661 8.661 0 0 0 0 4.138 9.216 9.216 0 0 0 9.174 7.04H971.86a9.216 9.216 0 0 0 9.216-11.178L854.06 475.86a9.301 9.301 0 0 0-14.379-4.736 8.96 8.96 0 0 0-3.328 4.694M140.8 587.86L42.88 970.155a9.173 9.173 0 0 0 9.259 11.136h195.029a9.344 9.344 0 0 0 7.381-3.328 8.917 8.917 0 0 0 1.792-3.67 8.661 8.661 0 0 0 0.043-4.138L158.379 587.86a8.96 8.96 0 0 0-3.328-4.65 9.387 9.387 0 0 0-5.419-1.792 9.387 9.387 0 0 0-5.547 1.792 8.96 8.96 0 0 0-3.285 4.65" fill="#00E5E5" p-id="9875"></path><path d="M313.43 271.36L135.082 970.155a8.96 8.96 0 0 0 1.706 7.594 9.088 9.088 0 0 0 7.04 3.542h356.822a9.216 9.216 0 0 0 9.258-11.094L331.051 271.275a8.96 8.96 0 0 0-3.328-4.651 9.387 9.387 0 0 0-5.462-1.792 9.387 9.387 0 0 0-5.504 1.792 8.96 8.96 0 0 0-3.328 4.693" fill="#006EFF" p-id="9876"></path><path d="M621.141 49.11a8.96 8.96 0 0 0-3.328-4.651 9.387 9.387 0 0 0-5.504-1.792 9.387 9.387 0 0 0-5.461 1.792 8.96 8.96 0 0 0-3.328 4.65L359.723 970.155a9.173 9.173 0 0 0 9.216 11.093h487.253a9.344 9.344 0 0 0 7.339-3.328 9.472 9.472 0 0 0 1.877-3.67 9.173 9.173 0 0 0 0-4.095L621.141 49.109z" fill="#006EFF" p-id="9877"></path><path d="M442.027 372.95L287.36 970.111a8.832 8.832 0 0 0 1.835 7.85 9.216 9.216 0 0 0 7.381 3.371h308.608a9.387 9.387 0 0 0 7.424-3.413 9.301 9.301 0 0 0 1.835-7.808L459.648 372.907a8.96 8.96 0 0 0-3.328-4.608 9.387 9.387 0 0 0-5.504-1.835 9.387 9.387 0 0 0-5.461 1.835 8.96 8.96 0 0 0-3.328 4.608" fill="#00E5E5" p-id="9878"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,146 +0,0 @@
// Inspired from https://github.com/netfarm/lehttp_overrides
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
// expired
const String kSha1DstX3 = 'DAC9024F54D8F6DF94935FB1732638CA6AD77C13';
// ISRG Root X1
const String kIsrgRootX1 = '''-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----''';
const String kIsrgRootX1Alt = '''-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
-----END CERTIFICATE-----
''';
const String kLetsEncryptCert = '''-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----
''';
String _hexConverter(Uint8List bytes) {
final StringBuffer buffer = StringBuffer();
for (int part in bytes) {
buffer.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
}
return buffer.toString().toUpperCase();
}
class WindowsHttpOverrides extends HttpOverrides {
static bool? _initRootCert;
final bool allowExpiredDSTX3;
static bool _addRootCert() {
if (Platform.isWindows) {
final List<int> cert = ascii.encode(kIsrgRootX1);
SecurityContext.defaultContext.setTrustedCertificatesBytes(cert);
final List<int> certAlt = ascii.encode(kIsrgRootX1Alt);
SecurityContext.defaultContext.setTrustedCertificatesBytes(certAlt);
final List<int> certAlt2 = ascii.encode(kLetsEncryptCert);
SecurityContext.defaultContext.setTrustedCertificatesBytes(certAlt2);
}
return true;
}
WindowsHttpOverrides({this.allowExpiredDSTX3 = false}) {
_initRootCert ??= _addRootCert();
}
@override
HttpClient createHttpClient(SecurityContext? context) {
final HttpClient client = super.createHttpClient(context);
if (allowExpiredDSTX3) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) =>
_hexConverter(cert.sha1) == kSha1DstX3;
}
return client;
}
}

View File

@@ -0,0 +1,40 @@
{
"account": "Уліковы запіс",
"unlock": "Разблакіраваць",
"recoveryKey": "Ключ аднаўлення",
"counterAppBarTitle": "Лічыльнік",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"onBoardingGetStarted": "Пачаць",
"codeIssuerHint": "Выдавец",
"codeSecretKeyHint": "Сакрэтны ключ",
"secret": "Сакрэт",
"notes": "Нататкі",
"codeTagHint": "Тэг",
"saveAction": "Захаваць",
"blog": "Блог",
"changePassword": "Змяніць пароль",
"data": "Даныя",
"importLabel": "Імпарт",
"yes": "Так",
"no": "Не",
"email": "Электронная пошта",
"support": "Падтрымка",
"settings": "Налады",
"pleaseTryAgain": "Калі ласка, паспрабуйце яшчэ раз",
"delete": "Выдаліць",
"enterYourPasswordHint": "Увядзіце ваш пароль",
"faq": "Частыя пытанні",
"deleteAccount": "Выдаліць уліковы запіс",
"noDeleteAccountAction": "Не, выдаліць уліковы запіс",
"sendEmail": "Адправіць ліст",
"createNewAccount": "Стварыць новы ўліковы запіс",
"confirmPassword": "Пацвердзіць пароль",
"close": "Закрыць",
"oopsSomethingWentWrong": "Штосьці пайшло не так.",
"language": "Мова",
"security": "Бяспека",
"searchHint": "Пошук...",
"search": "Пошук"
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -478,5 +478,6 @@
"enterPin": "Saisir le code PIN",
"setNewPin": "Définir un nouveau code PIN",
"importFailureDescNew": "Impossible de lire le fichier sélectionné.",
"authToViewPasskey": "Veuillez vous authentifier pour afficher la clé d'accès"
"authToViewPasskey": "Veuillez vous authentifier pour afficher la clé d'accès",
"appLockOfflineModeWarning": "Vous avez choisi de fonctionner sans sauvegardes. Si vous oubliez votre outil Applock, vous serez bloqué dans l'accès à vos données."
}

View File

@@ -483,5 +483,6 @@
"importFailureDescNew": "Impossibile elaborare il file selezionato.",
"appLockNotEnabled": "Blocco app non abilitato",
"appLockNotEnabledDescription": "Si prega di abilitare il blocco dell'app da Sicurezza > Blocco App",
"authToViewPasskey": "Autenticati per visualizzare le tue passkey"
"authToViewPasskey": "Autenticati per visualizzare le tue passkey",
"appLockOfflineModeWarning": "Hai scelto di procedere senza backup. Se dimentichi il tuo codice di blocco dell'app, non potrai più accedere ai tuoi dati."
}

View File

@@ -19,6 +19,20 @@
"pleaseVerifyDetails": "詳細を確認し、もう一度お試しください",
"codeIssuerHint": "発行者",
"codeSecretKeyHint": "秘密鍵",
"secret": "シークレット",
"all": "すべて",
"notes": "ノート",
"notesLengthLimit": "ノートは {count} 文字までです",
"@notesLengthLimit": {
"description": "Text to indicate the maximum number of characters allowed for notes",
"placeholders": {
"count": {
"description": "The maximum number of characters allowed for notes",
"type": "int",
"example": "100"
}
}
},
"codeAccountHint": "アカウント (you@domain.com)",
"codeTagHint": "タグ",
"accountKeyType": "鍵の種類",
@@ -34,6 +48,9 @@
"nextTotpTitle": "次のコード",
"deleteCodeTitle": "コードを削除しますか?",
"deleteCodeMessage": "本当にこのコードを削除してもよろしいですか?この決定は元に戻せません。",
"trashCode": "コードを削除しますか?",
"trashCodeMessage": "{account} のコードをゴミ箱に入れてもよろしいですか?",
"trash": "ゴミ箱",
"viewLogsAction": "ログの表示",
"sendLogsDescription": "問題のデバッグに役立つログが送信されます。機密情報が記録されないように予防措置を講じていますが、共有する前にこれらのログを確認することをお勧めします。",
"preparingLogsTitle": "ログを準備中...",
@@ -100,6 +117,7 @@
"emailVerificationToggle": "メール認証",
"emailVerificationEnableWarning": "アカウントから閉め出されるのを防ぐために、メール認証を有効にする前にメール 2FA のコピーが ente Auth 外に保管されていることを確認してください。",
"authToChangeEmailVerificationSetting": "メール認証を変更するためには認証が必要です",
"authenticateGeneric": "認証してください",
"authToViewYourRecoveryKey": "回復キーを表示するためには認証が必要です",
"authToChangeYourEmail": "メールアドレスを変更するためには認証が必要です",
"authToChangeYourPassword": "パスワードを変更するためには認証が必要です",
@@ -127,6 +145,8 @@
"leaveFamily": "ファミリープランから退会",
"leaveFamilyMessage": "本当にファミリープランを退会しますか?",
"inFamilyPlanMessage": "ファミリープランに入会しています!",
"hintForMobile": "コードを長押しすると、編集または削除できます。",
"hintForDesktop": "コードを右クリックすると、編集または削除できます。",
"scan": "読み取り",
"scanACode": "コードを読み取り",
"verify": "認証",
@@ -182,6 +202,10 @@
"scanAQrCode": "QRコードを読み取り",
"enterDetailsManually": "手動で詳細を入力する",
"edit": "編集",
"share": "共有",
"shareCodes": "コードを共有",
"shareCodesDuration": "コードを共有したい期間を選択してください。",
"restore": "復元",
"copiedToClipboard": "クリップボードにコピーしました",
"copiedNextToClipboard": "次のコードをクリップボードにコピーしました",
"error": "エラー",
@@ -335,6 +359,7 @@
"sigInBackupReminder": "コードをエクスポートして、復元するためのバックアップがあることを確認してください。",
"offlineModeWarning": "あなたはバックアップなしに続行することを選択しました。コードを安全に保つために手動でのバックアップを行ってください。",
"showLargeIcons": "大きなアイコンを表示",
"compactMode": "コンパクトモード",
"shouldHideCode": "コードを隠す",
"doubleTapToViewHiddenCode": "項目をダブルタップしてコードを閲覧できます",
"focusOnSearchBar": "アプリの起動時、検索欄にフォーカスする",
@@ -455,5 +480,9 @@
"pinLock": "PIN",
"enterPin": "PINを入力してください",
"setNewPin": "新しいPINを設定",
"importFailureDescNew": "選択されたファイルを解析できませんでした。"
"importFailureDescNew": "選択されたファイルを解析できませんでした。",
"appLockNotEnabled": "アプリロックが有効になっていません",
"appLockNotEnabledDescription": "セキュリティ > アプリロック からアプリロックを有効化してください",
"authToViewPasskey": "パスキーを見るには認証してください",
"appLockOfflineModeWarning": "バックアップなしで進むことを選択しました。アプリロックを忘れると、データにアクセスできなくなります。"
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -460,7 +460,7 @@
"viewRawCodes": "Zobacz surowe kody",
"rawCodes": "Surowe kody",
"rawCodeData": "Dane surowego kodu",
"appLock": "Blokada dostępu do aplikacji",
"appLock": "Blokada aplikacji",
"noSystemLockFound": "Nie znaleziono blokady systemowej",
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Aby włączyć blokadę aplikacji, należy skonfigurować hasło urządzenia lub blokadę ekranu w ustawieniach systemu.",
"autoLock": "Automatyczna blokada",
@@ -482,6 +482,7 @@
"setNewPin": "Ustaw nowy kod PIN",
"importFailureDescNew": "Nie udało się przetworzyć wybranego pliku.",
"appLockNotEnabled": "Blokada aplikacji nie jest włączona",
"appLockNotEnabledDescription": "Prosimy włączyć blokadę aplikacji z Zabezpieczenia > Blokada Aplikacji",
"authToViewPasskey": "Prosimy uwierzytelnić się, aby wyświetlić klucz dostępu"
"appLockNotEnabledDescription": "Prosimy włączyć blokadę aplikacji z Zabezpieczenia > Blokada aplikacji",
"authToViewPasskey": "Prosimy uwierzytelnić się, aby wyświetlić klucz dostępu",
"appLockOfflineModeWarning": "Wybrano kontynuowanie bez kopii zapasowych. Jeśli zapomnisz blokady aplikacji, utracisz dostęp do swoich danych."
}

View File

@@ -6,20 +6,20 @@
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"onBoardingBody": "Proteja os seus códigos 2FA",
"onBoardingBody": "Copie com segurança seus códigos 2FA",
"onBoardingGetStarted": "Introdução",
"setupFirstAccount": "Configure sua primeira conta",
"importScanQrCode": "Escanear QR code",
"qrCode": "QR Code",
"importEnterSetupKey": "Insira uma chave de configuração",
"importAccountPageTitle": "Inserir dados da conta",
"secretCanNotBeEmpty": "A chave secreta não pode ser vazia",
"importAccountPageTitle": "Inserir detalhes da conta",
"secretCanNotBeEmpty": "A chave secreta não pode estar vazia",
"bothIssuerAndAccountCanNotBeEmpty": "O emissor e a conta não podem estar vazios",
"incorrectDetails": "Detalhes incorretos",
"pleaseVerifyDetails": "Por favor, verifique os detalhes e tente novamente",
"pleaseVerifyDetails": "Verifique os detalhes e tente novamente",
"codeIssuerHint": "Emissor",
"codeSecretKeyHint": "Chave secreta",
"secret": "Secreto",
"secret": "Segredo",
"all": "Todos",
"notes": "Notas",
"notesLengthLimit": "Notas tem um limite de até {count} caracteres",
@@ -33,7 +33,7 @@
}
}
},
"codeAccountHint": "Conta (você@domínio.com)",
"codeAccountHint": "Conta (voce@dominio.com)",
"codeTagHint": "Etiqueta",
"accountKeyType": "Tipo de chave",
"sessionExpired": "Sessão expirada",
@@ -43,19 +43,19 @@
"pleaseLoginAgain": "Entre novamente",
"loggingOut": "Saindo...",
"timeBasedKeyType": "Baseado no horário (TOTP)",
"counterBasedKeyType": "Baseado num contador (HOTP)",
"counterBasedKeyType": "Baseado no contador (HOTP)",
"saveAction": "Salvar",
"nextTotpTitle": "avançar",
"deleteCodeTitle": "Apagar código?",
"deleteCodeTitle": "Excluir código?",
"deleteCodeMessage": "Deseja mesmo excluir este código? Esta ação é irreversível.",
"trashCode": "Excluir código?",
"trashCodeMessage": "Você tem certeza de que quer excluir o código para {account}?",
"trash": "Excluir",
"viewLogsAction": "Ver logs",
"sendLogsDescription": "Isto compartilhará seus dados para nos ajudarmos a resolver seu problema. Enquanto tomamos precauções para ter certeza que as informações sensíveis não estejam registradas, nós encorajamos você a visualizar esses dados antes de compartilhá-los.",
"preparingLogsTitle": "Preparando logs...",
"emailLogsTitle": "Logs (e-mail)",
"emailLogsMessage": "Envie os logs para {email}",
"viewLogsAction": "Ver registros",
"sendLogsDescription": "Isso compartilhará seus dados para lhe ajudarmos a resolver seu problema. Enquanto tomamos precauções para ter certeza que as informações sensíveis não estejam registradas, nós encorajamos você a visualizar esses dados antes de compartilhá-los.",
"preparingLogsTitle": "Preparando registros...",
"emailLogsTitle": "Registros (e-mail)",
"emailLogsMessage": "Envie os registros para {email}",
"@emailLogsMessage": {
"placeholders": {
"email": {
@@ -64,9 +64,9 @@
}
},
"copyEmailAction": "Copiar e-mail",
"exportLogsAction": "Exportar logs",
"exportLogsAction": "Exportar registros",
"reportABug": "Informe um erro",
"crashAndErrorReporting": "Relatórios de erros",
"crashAndErrorReporting": "Relatórios de erros e falhas",
"reportBug": "Informar erro",
"emailUsMessage": "Envie um e-mail para {email}",
"@emailUsMessage": {
@@ -76,8 +76,8 @@
}
}
},
"contactSupport": "Falar com o Suporte",
"rateUsOnStore": "Avalie-nos na {storeName}",
"contactSupport": "Contatar suporte",
"rateUsOnStore": "Avalies na {storeName}",
"blog": "Blog",
"merchandise": "Produtos",
"verifyPassword": "Verificar senha",
@@ -96,33 +96,33 @@
"data": "Dados",
"importCodes": "Importar códigos",
"importTypePlainText": "Texto simples",
"importTypeEnteEncrypted": "Exportação do Ente criptografada",
"importTypeEnteEncrypted": "Exportação criptografada do Ente",
"passwordForDecryptingExport": "Senha para descriptografar a exportação",
"passwordEmptyError": "A senha não pode estar vazia",
"importFromApp": "Importar códigos do {appName}",
"importGoogleAuthGuide": "Exporte suas contas do Google Authenticator para um QR code usando a opção \"Transferir contas\". Então, usando outro dispositivo, escaneie o QR code.\n\nDica: você pode usar a câmera do notebook para fotografar o QR code.",
"importGoogleAuthGuide": "Exporte suas contas do Google Authenticator para um QR code usando a opção \"Transferir Contas\". Então, usando outro dispositivo, escaneie o código.\n\nDica: Você pode usar a câmera do seu notebook para fotografar o QR code.",
"importSelectJsonFile": "Selecionar arquivo JSON",
"importSelectAppExport": "Selecione o arquivo de exportação do aplicativo {appName}",
"importEnteEncGuide": "Selecione o arquivo JSON criptografado exportado do Ente",
"importRaivoGuide": "Use a opção \"Exportar OTPs para arquivo Zip\" nas configurações do Raivo.\n\nExtraia o arquivo zip e importe o arquivo JSON.",
"importBitwardenGuide": "Use a opção \"Exportar cofre\" nas configurações do Bitwarden e importe o arquivo JSON não criptografado.",
"importAegisGuide": "Use a opção \"Exportar cofre\" nas Configurações do Aegis.\n\nSe o seu cofre estiver criptografado, você precisará inserir a senha do cofre para descriptografá-lo.",
"import2FasGuide": "Use a opção \"Configurações->Exportar cópia de segurança\" no aplicativo 2FAS.\n\nSe a cópia de segurança estiver criptografada, será necessário inserir a senha para descriptografá-la",
"importLastpassGuide": "Use a opção \"Transferir contas\" nas configurações do LastPass Authenticator e pressione \"Exportar contas para arquivo\". Importe o arquivo JSON baixado.",
"importRaivoGuide": "Use a opção \"Exportar OTPs para arquivo zip\" nas opções de Raivo.\n\nExtraia o arquivo zip e importe o arquivo JSON.",
"importBitwardenGuide": "Use a opção \"Exportar cofre\" nas ferramentas do Bitwarden e importe o arquivo JSON não criptografado.",
"importAegisGuide": "Use a opção \"Exportar cofre\" nas opções de Aegis\n\nSe o cofre estiver criptografado, você precisará inserir a senha do cofre para descriptografá-lo.",
"import2FasGuide": "Use a opção \"Opções-> Exportar cópia de segurança\" em 2FAS.\n\nSe a cópia de segurança estiver criptografada, você precisará inserir a senha para descriptografá-la",
"importLastpassGuide": "Use a opção \"Transferir contas\" nas opções do LastPass Authenticator e pressione \"Exportar contas para arquivo\". Importe o arquivo JSON baixado.",
"exportCodes": "Exportar códigos",
"importLabel": "Importar",
"importInstruction": "Por favor, selecione um arquivo que contenha uma lista de códigos no seguinte formato",
"importInstruction": "Selecione um arquivo que contenha uma lista de códigos no formato a seguir",
"importCodeDelimiterInfo": "Os códigos podem ser separados por uma vírgula ou uma nova linha",
"selectFile": "Selecionar arquivo",
"emailVerificationToggle": "Verificação por e-mail",
"emailVerificationEnableWarning": "Para evitar ficar bloqueado do acesso a sua conta, certifique-se de armazenar uma cópia do código 2FA do seu e-mail fora do Ente Auth antes de habilitar a verificação por e-mail.",
"authToChangeEmailVerificationSetting": "Por favor, autentique-se para alterar a verificação por e-mail",
"authenticateGeneric": "Por favor, autentique",
"authToViewYourRecoveryKey": "Por favor, autentique-se para visualizar sua chave de recuperação",
"authToChangeYourEmail": "Por favor, autentique-se para alterar o seu e-mail",
"authToChangeYourPassword": "Por favor, autentique-se para alterar sua senha",
"authToViewSecrets": "Por favor, autentique-se para ver as suas chaves secretas",
"authToInitiateSignIn": "Por favor, autentique-se para iniciar o login para um backup.",
"emailVerificationEnableWarning": "Para evitar ser bloqueado da sua conta, certifique-se de guardar uma cópia do seu e-mail 2FA fora do Ente Auth antes de ativar a verificação de e-mail.",
"authToChangeEmailVerificationSetting": "Autentique-se para altere o e-mail de verificação",
"authenticateGeneric": "Autentique",
"authToViewYourRecoveryKey": "Autentique para ver sua chave de recuperação",
"authToChangeYourEmail": "Autentique para alterar o seu e-mail",
"authToChangeYourPassword": "Autentique para alterar sua senha",
"authToViewSecrets": "Autentique para ver suas chaves secretas",
"authToInitiateSignIn": "Autentique para iniciar sessão para fazer uma cópia de segurança.",
"ok": "OK",
"cancel": "Cancelar",
"yes": "Sim",
@@ -159,7 +159,7 @@
"recoverAccount": "Recuperar conta",
"enterRecoveryKeyHint": "Digite a chave de recuperação",
"recover": "Recuperar",
"contactSupportViaEmailMessage": "Por favor, envie um e-mail para {email} a partir do seu endereço de e-mail registrado",
"contactSupportViaEmailMessage": "Envie um e-mail para {email} a partir do seu endereço de e-mail registrado",
"@contactSupportViaEmailMessage": {
"placeholders": {
"email": {
@@ -176,7 +176,7 @@
"deleteAccountQuery": "Estamos tristes com sua decisão. Você encontrou algum problema?",
"yesSendFeedbackAction": "Sim, enviar feedback",
"noDeleteAccountAction": "Não, excluir conta",
"initiateAccountDeleteTitle": "Por favor, autentique-se para iniciar a exclusão de conta",
"initiateAccountDeleteTitle": "Autentique para iniciar a exclusão de conta",
"sendEmail": "Enviar e-mail",
"createNewAccount": "Criar nova conta",
"weakStrength": "Fraca",
@@ -190,10 +190,10 @@
"social": "Redes sociais",
"security": "Segurança",
"lockscreen": "Tela de bloqueio",
"authToChangeLockscreenSetting": "Por favor, autentique-se para alterar a configuração da tela de bloqueio",
"authToChangeLockscreenSetting": "Autentique para alterar a opção de tela de bloqueio",
"deviceLockEnablePreSteps": "Para ativar o bloqueio do dispositivo, configure a senha do dispositivo ou o bloqueio de tela nas configurações do seu sistema.",
"viewActiveSessions": "Ver sessões ativas",
"authToViewYourActiveSessions": "Por favor, autentique-se para ver as sessões ativas",
"authToViewYourActiveSessions": "Autentique para ver suas sessões ativas",
"searchHint": "Buscar...",
"search": "Buscar",
"sorryUnableToGenCode": "Desculpe, não foi possível gerar um código para {issuerName}",
@@ -242,16 +242,16 @@
"resetPasswordTitle": "Redefinir senha",
"encryptionKeys": "Chaves de criptografia",
"passwordWarning": "Não salvamos esta senha, então se você esquecê-la, <underline>não podemos descriptografar seus dados</underline>",
"enterPasswordToEncrypt": "Digite uma senha que podemos usar para criptografar seus dados",
"enterPasswordToEncrypt": "Insira uma senha que podemos usar para criptografar seus dados",
"enterNewPasswordToEncrypt": "Insira uma nova senha para criptografar seus dados",
"passwordChangedSuccessfully": "A senha foi alterada",
"generatingEncryptionKeys": "Gerando chaves de criptografia...",
"continueLabel": "Continuar",
"insecureDevice": "Dispositivo inseguro",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves seguras neste dispositivo.\n\npor favor, faça o login com um dispositivo diferente.",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves de segurança nesse dispositivo.\n\ninicie sessão em um dispositivo diferente.",
"howItWorks": "Como funciona",
"ackPasswordLostWarning": "Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são <underline>criptografados de ponta a ponta</underline>.",
"loginTerms": "Ao clicar em login, eu concordo com os <u-terms>termos de serviço</u-terms> e a <u-policy>política de privacidade</u-policy>",
"loginTerms": "Ao clicar em iniciar sessão, eu concordo com os <u-terms>termos de serviço</u-terms> e a <u-policy>política de privacidade</u-policy>",
"logInLabel": "Entrar",
"logout": "Sair",
"areYouSureYouWantToLogout": "Deseja mesmo sair?",
@@ -259,15 +259,15 @@
"exit": "Sair",
"verifyingRecoveryKey": "Verificando chave de recuperação...",
"recoveryKeyVerified": "Chave de recuperação verificada",
"recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigado por verificar.\n\nLembre-se de manter o backup seguro de sua chave de recuperação.",
"invalidRecoveryKey": "A chave de recuperação que você digitou não é válida. Certifique-se de que contém 24 palavras e verifique a ortografia de cada uma.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.",
"recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigada por verificar.\n\nLembre-se de manter sua chave de recuperação copiada com segurança.",
"invalidRecoveryKey": "A chave de recuperação que você inseriu não é válida. Certifique-se de conter 24 caracteres, e verifique a ortografia de cada um deles.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.",
"recreatePasswordTitle": "Redefinir senha",
"recreatePasswordBody": "Não é possível verificar a sua senha no dispositivo atual, mas podemos regenerá-la para que funcione em todos os dispositivos. \n\nEntre com a sua chave de recuperação e regenere sua senha (você pode usar a mesma se quiser).",
"invalidKey": "Chave inválida",
"tryAgain": "Tente novamente",
"viewRecoveryKey": "Ver chave de recuperação",
"confirmRecoveryKey": "Confirme a chave de recuperação",
"recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esquecer sua senha. Você pode encontrar sua chave de recuperação em Configurações > Conta.\n\nDigite sua chave de recuperação aqui para verificar se você a salvou corretamente.",
"recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esqueceu sua senha. Você pode encontrar sua chave de recuperação em Opções > Conta.\n\nInsira sua chave de recuperação aqui para verificar se você a salvou corretamente.",
"confirmYourRecoveryKey": "Confirme sua chave de recuperação",
"confirm": "Confirmar",
"emailYourLogs": "Enviar logs por e-mail",
@@ -275,10 +275,10 @@
"copyEmailAddress": "Copiar endereço de e-mail",
"exportLogs": "Exportar logs",
"enterYourRecoveryKey": "Digite a chave de recuperação",
"tempErrorContactSupportIfPersists": "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte.",
"tempErrorContactSupportIfPersists": "Parece que algo deu errado. Tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de ajuda.",
"networkHostLookUpErr": "Não foi possível conectar-se ao Ente, verifique suas configurações de rede e entre em contato com o suporte se o erro persistir.",
"networkConnectionRefusedErr": "Não foi possível conectar ao Ente, tente novamente após algum tempo. Se o erro persistir, entre em contato com o suporte.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Parece que algo deu errado. Tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de ajuda.",
"about": "Sobre",
"weAreOpenSource": "Nosso código é aberto!",
"privacy": "Privacidade",
@@ -292,12 +292,12 @@
"checking": "Verificando...",
"youAreOnTheLatestVersion": "Você está na versão mais recente",
"warning": "Atenção",
"exportWarningDesc": "O arquivo exportado contém informações confidenciais. Por favor, armazene-o com segurança.",
"exportWarningDesc": "O arquivo exportado contém informações confidenciais. Armazene-o com segurança.",
"iUnderStand": "Entendo",
"@iUnderStand": {
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Por favor, autentique-se para exportar seus códigos",
"authToExportCodes": "Autentique para exportar seus códigos",
"importSuccessTitle": "Oba!",
"importSuccessDesc": "Você importou {count} códigos!",
"@importSuccessDesc": {
@@ -310,9 +310,9 @@
}
},
"sorry": "Desculpe",
"importFailureDesc": "Não foi possível analisar o arquivo selecionado.\nPor favor, escreva para support@ente.io se precisar de ajuda!",
"importFailureDesc": "Não foi possível analisar o arquivo selecionado. Escreva para support@ente.io se precisar de ajuda!",
"pendingSyncs": "Atenção",
"pendingSyncsWarningBody": "Alguns de seus códigos não foram salvos.\n\nPor favor, certifique-se que você possui um backup para esses códigos antes de sair.",
"pendingSyncsWarningBody": "Alguns de seus códigos não foram salvos.\n\nCertifique-se que você possui uma cópia desses códigos antes de sair.",
"checkInboxAndSpamFolder": "Verifique sua caixa de entrada (e spam) para concluir a verificação",
"tapToEnterCode": "Toque para inserir código",
"resendEmail": "Reenviar e-mail",
@@ -328,20 +328,20 @@
}
},
"activeSessions": "Sessões ativas",
"somethingWentWrongPleaseTryAgain": "Algo deu errado. Por favor, tente outra vez",
"somethingWentWrongPleaseTryAgain": "Algo deu errado. Tente outra vez",
"thisWillLogYouOutOfThisDevice": "Isso fará com que você saia deste dispositivo!",
"thisWillLogYouOutOfTheFollowingDevice": "Isso fará com que você saia do seguinte dispositivo:",
"thisWillLogYouOutOfTheFollowingDevice": "Isso fará você sair do dispositivo a seguir:",
"terminateSession": "Sair?",
"terminate": "Encerrar",
"thisDevice": "Esse dispositivo",
"toResetVerifyEmail": "Para redefinir a sua senha, por favor verifique o seu email primeiro.",
"toResetVerifyEmail": "Para redefinir sua senha, verifique seu e-mail primeiramente.",
"thisEmailIsAlreadyInUse": "Este e-mail já está em uso",
"verificationFailedPleaseTryAgain": "Falha na verificação. Tente novamente",
"yourVerificationCodeHasExpired": "Seu código de verificação expirou",
"incorrectCode": "Código incorreto",
"sorryTheCodeYouveEnteredIsIncorrect": "Desculpe, o código que você inseriu está incorreto",
"sorryTheCodeYouveEnteredIsIncorrect": "O código inserido está incorreto",
"emailChangedTo": "E-mail alterado para {newEmail}",
"authenticationFailedPleaseTryAgain": "Falha na autenticação. Por favor, tente novamente",
"authenticationFailedPleaseTryAgain": "A autenticação falhou. Tente novamente",
"authenticationSuccessful": "Autenticado!",
"twofactorAuthenticationSuccessfullyReset": "Autenticação de dois fatores redefinida com sucesso",
"incorrectRecoveryKey": "Chave de recuperação incorreta",
@@ -356,8 +356,8 @@
"useOffline": "Usar sem backups",
"signInToBackup": "Entre para fazer backup de seus códigos",
"singIn": "Entrar",
"sigInBackupReminder": "Por favor, exporte seus códigos para garantir que você tenha um backup do qual você possa restaurar.",
"offlineModeWarning": "Você escolheu prosseguir sem backups. Por favor, faça backups manuais para ter certeza de que seus códigos estão seguros.",
"sigInBackupReminder": "Exporte seus códigos para garantir que você tenha uma cópia para restaurar.",
"offlineModeWarning": "Você decidiu prosseguir sem cópias. Faça cópias manuais para garantir que seus códigos estejam seguros.",
"showLargeIcons": "Mostrar ícones grandes",
"compactMode": "Modo compacto",
"shouldHideCode": "Ocultar códigos",
@@ -406,15 +406,15 @@
"@goToSettings": {
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
},
"androidGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Vá em 'Configurações > Segurança' para adicionar autenticação biométrica.",
"androidGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Vá em 'Configurações > Segurança' para adicionar a autenticação biométrica.",
"@androidGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side."
},
"iOSLockOut": "A Autenticação Biométrica está desativada. Por favor, bloqueie e desbloqueie sua tela para ativá-la.",
"iOSLockOut": "A autenticação biométrica está desativada. Bloqueie e desbloqueie sua tela para ativá-la.",
"@iOSLockOut": {
"description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side."
},
"iOSGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Por favor, ative o Touch ID ou o Face ID no seu telefone.",
"iOSGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Ative o ID de toque ou ID de rosto em seu celular.",
"@iOSGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side."
},
@@ -425,10 +425,10 @@
"noInternetConnection": "Não conectado à internet",
"pleaseCheckYourInternetConnectionAndTryAgain": "Verifique sua conexão com a internet e tente novamente.",
"signOutFromOtherDevices": "Sair da conta em outros dispositivos",
"signOutOtherBody": "Se você acha que alguém pode saber sua senha, você pode forçar todos os outros dispositivos que estão com sua conta a desconectar.",
"signOutOtherBody": "Se você acha que alguém possa saber da sua senha, você pode forçar desconectar sua conta de outros dispositivos.",
"signOutOtherDevices": "Sair em outros dispositivos",
"doNotSignOut": "Não sair",
"hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)",
"hearUsWhereTitle": "Como você descobriu o Ente? (opcional)",
"hearUsExplanation": "Não sabemos como você encontrou nosso app. Seria útil se você nos contasse!",
"recoveryKeySaved": "Chave de recuperação salva na pasta Downloads!",
"waitingForBrowserRequest": "Aguardando solicitação do navegador...",
@@ -436,12 +436,12 @@
"passkey": "Chave de acesso",
"passKeyPendingVerification": "A verificação ainda está pendente",
"loginSessionExpired": "Sessão expirada",
"loginSessionExpiredDetails": "Sua sessão expirou. Por favor, entre novamente.",
"loginSessionExpiredDetails": "Sua sessão expirou. Registre-se novamente.",
"developerSettingsWarning": "Deseja mesmo alterar os ajustes de Desenvolvedor?",
"developerSettings": "Ajustes de Desenvolvedor",
"serverEndpoint": "Endpoint do servidor",
"invalidEndpoint": "Endpoint inválido",
"invalidEndpointMessage": "Desculpe, o endpoint que você inseriu é inválido. Por favor, insira um endpoint válido e tente novamente.",
"invalidEndpointMessage": "Desculpe, o ponto de acesso inserido é inválido. Insira um ponto de acesso válido e tente novamente.",
"endpointUpdatedMessage": "O endpoint foi atualizado",
"customEndpoint": "Conectado a {endpoint}",
"pinText": "Fixar",
@@ -483,5 +483,6 @@
"importFailureDescNew": "Não foi possível analisar o arquivo selecionado.",
"appLockNotEnabled": "Bloqueio de aplicativo não ativado",
"appLockNotEnabledDescription": "Ative o bloqueio de aplicativo em Segurança > Bloqueio de aplicativo",
"authToViewPasskey": "Autentique para ver a sua chave de acesso"
"authToViewPasskey": "Autentique para ver a sua chave de acesso",
"appLockOfflineModeWarning": "Você prosseguiu sem cópias de segurança. Caso, se esqueça de seu aplicativo de bloqueio, você não poderá mais acessar seus dados."
}

View File

@@ -19,6 +19,20 @@
"pleaseVerifyDetails": "Пожалуйста, проверьте детали и попробуйте еще раз",
"codeIssuerHint": "Эмитент",
"codeSecretKeyHint": "Секретный ключ",
"secret": "Секрет",
"all": "Все",
"notes": "Заметки",
"notesLengthLimit": "Заметки могут быть не более {count} символов",
"@notesLengthLimit": {
"description": "Text to indicate the maximum number of characters allowed for notes",
"placeholders": {
"count": {
"description": "The maximum number of characters allowed for notes",
"type": "int",
"example": "100"
}
}
},
"codeAccountHint": "Аккаунт (you@domain.com)",
"codeTagHint": "Метка",
"accountKeyType": "Тип ключа",
@@ -34,6 +48,9 @@
"nextTotpTitle": "далее",
"deleteCodeTitle": "Удалить код?",
"deleteCodeMessage": "Вы уверены, что хотите удалить этот код? Это действие необратимо.",
"trashCode": "Удалить код?",
"trashCodeMessage": "Вы уверены, что хотите удалить код для {account}?",
"trash": "Удалить",
"viewLogsAction": "Посмотреть журнал",
"sendLogsDescription": "Это отправит все журналы, чтобы помочь нам отладить вашу проблему. Хотя мы принимаем меры предосторожности, чтобы конфиденциальная информация не регистрировалась, мы рекомендуем вам просмотреть эти журналы, прежде чем делиться ими.",
"preparingLogsTitle": "Подготовка журналов...",
@@ -100,6 +117,7 @@
"emailVerificationToggle": "Подтверждение электронной почты",
"emailVerificationEnableWarning": "Если вы храните у нас двухфакторную аутентификацию в своей электронной почте, включение проверки электронной почты может привести к тупиковой ситуации. Если у вас заблокирован доступ к одной службе, возможно, вы не сможете войти в другую.",
"authToChangeEmailVerificationSetting": "Авторизуйтесь, чтобы изменить подтверждение электронной почты",
"authenticateGeneric": "Пожалуйста, авторизуйтесь",
"authToViewYourRecoveryKey": "Пожалуйста, авторизуйтесь для просмотра вашего ключа восстановления",
"authToChangeYourEmail": "Пожалуйста, авторизуйтесь, чтобы изменить адрес электронной почты",
"authToChangeYourPassword": "Пожалуйста, авторизуйтесь, чтобы изменить пароль",
@@ -127,6 +145,8 @@
"leaveFamily": "Покинуть семью",
"leaveFamilyMessage": "Вы уверены, что хотите отказаться от семейного плана?",
"inFamilyPlanMessage": "Вы на семейном плане!",
"hintForMobile": "Длительное нажмите на код для редактирования или удаления.",
"hintForDesktop": "Щелкните правой кнопкой мыши по коду, чтобы изменить или удалить.",
"scan": "Сканировать",
"scanACode": "Сканировать QR-код",
"verify": "Подтвердить",
@@ -171,6 +191,7 @@
"security": "Безопасность",
"lockscreen": "Экран блокировки",
"authToChangeLockscreenSetting": "Пожалуйста, авторизуйтесь, чтобы изменить настройки экрана блокировки",
"deviceLockEnablePreSteps": "Чтобы включить блокировку устройства, пожалуйста, настройте пароль или блокировку экрана в настройках системы.",
"viewActiveSessions": "Просмотр активных сессий",
"authToViewYourActiveSessions": "Пожалуйста, авторизуйтесь для просмотра активных сессий",
"searchHint": "Поиск...",
@@ -181,6 +202,10 @@
"scanAQrCode": "Сканировать QR-код",
"enterDetailsManually": "Ввести детали вручную",
"edit": "Редактировать",
"share": "Поделиться",
"shareCodes": "Поделиться кодами",
"shareCodesDuration": "Выберите продолжительность, на которую вы хотите поделиться кодами.",
"restore": "Восстановить",
"copiedToClipboard": "Скопировано",
"copiedNextToClipboard": "Следующий код скопирован в буфер обмена",
"error": "Ошибка",
@@ -334,6 +359,7 @@
"sigInBackupReminder": "Экспортируйте свои коды, чтобы убедиться, что у вас есть резервная копия, из которой можно восстановить.",
"offlineModeWarning": "Вы решили продолжить без резервных копий. Пожалуйста, создайте резервные копии вручную, чтобы убедиться, что ваши коды в безопасности.",
"showLargeIcons": "Использовать большие значки",
"compactMode": "Компактный режим",
"shouldHideCode": "Скрыть коды",
"doubleTapToViewHiddenCode": "Вы можете нажать дважды на запись для просмотра кода",
"focusOnSearchBar": "Фокусировать поиск при запуске приложения",
@@ -454,5 +480,9 @@
"pinLock": "Pin Замок",
"enterPin": "Введите PIN",
"setNewPin": "Установите новый PIN",
"importFailureDescNew": "Не удалось обработать выбранный файл."
"importFailureDescNew": "Не удалось обработать выбранный файл.",
"appLockNotEnabled": "Блокировка приложения отключена",
"appLockNotEnabledDescription": "Пожалуйста, включите блокировку приложения в безопасности > Блокировка приложений",
"authToViewPasskey": "Пожалуйста, авторизуйтесь, чтобы просмотреть пароль",
"appLockOfflineModeWarning": "Вы решили продолжить работу без резервного копирования. Если вы забудете свой пароль, доступ к вашим данным будет заблокирован."
}

View File

@@ -0,0 +1,488 @@
{
"account": "Račun",
"unlock": "Odkleni",
"recoveryKey": "Ključ za obnovitev",
"counterAppBarTitle": "Števec",
"@counterAppBarTitle": {
"description": "Text shown in the AppBar of the Counter Page"
},
"onBoardingBody": "Varno varnostno kopirajte vaše kode 2FA",
"onBoardingGetStarted": "Začnite",
"setupFirstAccount": "Ustvarite svoj prvi račun",
"importScanQrCode": "Skenirajte QR kodo",
"qrCode": "QR koda",
"importEnterSetupKey": "Vnesite namestitveni ključ",
"importAccountPageTitle": "Vnesite podatke o računu",
"secretCanNotBeEmpty": "Skrivni ključ ne more biti prazen",
"bothIssuerAndAccountCanNotBeEmpty": "Izdajatelj in račun ne moreta biti prazna",
"incorrectDetails": "Nepravilni podatki",
"pleaseVerifyDetails": "Prosimo preverite vaše podatke in poizkusite ponovno",
"codeIssuerHint": "Izdajatelj",
"codeSecretKeyHint": "Skrivni ključ",
"secret": "Skrivni ključ",
"all": "Vsi",
"notes": "Opombe",
"notesLengthLimit": "Opombe so lahko dolge največ {count} znakov",
"@notesLengthLimit": {
"description": "Text to indicate the maximum number of characters allowed for notes",
"placeholders": {
"count": {
"description": "The maximum number of characters allowed for notes",
"type": "int",
"example": "100"
}
}
},
"codeAccountHint": "Račun (vi@domena.com)",
"codeTagHint": "Oznaka",
"accountKeyType": "Tip ključa",
"sessionExpired": "Seja je potekla",
"@sessionExpired": {
"description": "Title of the dialog when the users current session is invalid/expired"
},
"pleaseLoginAgain": "Prosimo, ponovno se prijavite",
"loggingOut": "Odjavljanje...",
"timeBasedKeyType": "Na osnovi časa (TOTP)",
"counterBasedKeyType": "Na osnovi števca (HOTP)",
"saveAction": "Shrani",
"nextTotpTitle": "naslednja",
"deleteCodeTitle": "Izbriši kodo?",
"deleteCodeMessage": "Ali ste prepričani, da želite izbrisati to kodo? To dejanje je nepovratno.",
"trashCode": "Premakni v smetnjak?",
"trashCodeMessage": "Ste prepričani da želite premakniti kodo za {account} v smetnjak?",
"trash": "V smetnjak",
"viewLogsAction": "Poglej loge",
"sendLogsDescription": "To nam bo poslalo vaše loge, da vam lahko pomagamo rešiti vašo težavo. Kljub temu, da se trudimo, da vaših zasebnih podatkov ne zapišemo v loge, vam priporočamo, da si jih pred deljenjem ogledate.",
"preparingLogsTitle": "Pripravljamo loge...",
"emailLogsTitle": "Pošlji loge po e-pošti",
"emailLogsMessage": "Prosim pošljite loge na {email}",
"@emailLogsMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"copyEmailAction": "Kopiraj e-pošto",
"exportLogsAction": "Izvozi loge",
"reportABug": "Prijavite napako",
"crashAndErrorReporting": "Poročanje o nesrečah in napakah",
"reportBug": "Prijavi napako",
"emailUsMessage": "Prosim, pišite nam na {email}",
"@emailUsMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"contactSupport": "Stik s podporo",
"rateUsOnStore": "Ocenite nas na {storeName}",
"blog": "Blog",
"merchandise": "Trgovina",
"verifyPassword": "Potrdite geslo",
"pleaseWait": "Prosim počakajte...",
"generatingEncryptionKeysTitle": "Generiramo ključe za šifriranje",
"recreatePassword": "Ponovno ustvarite geslo",
"recreatePasswordMessage": "Trenutna naprava, ni dovolj zmogljiva za preverjanje vašega gesla, zato ga moramo generirati na način, ki deluje z vsemi napravami.\n\nProsimo, prijavite se z vašim ključem za obnovo in ponovno ustvarite geslo (če želite lahko uporabite enako kot prej).",
"useRecoveryKey": "Uporabi ključ za obnovo",
"incorrectPasswordTitle": "Nepravilno geslo",
"welcomeBack": "Dobrodošli nazaj!",
"madeWithLoveAtPrefix": "ustvarjeno s ❤pri ",
"supportDevs": "Naročite se na <bold-green>ente</bold-green>, da nas podprete",
"supportDiscount": "Uporabite kupon \"AUTH\" za 10% popusta za prvo leto",
"changeEmail": "Sprememba e-poštnega naslova",
"changePassword": "Sprememba gesla",
"data": "Podatki",
"importCodes": "Uvozi kode",
"importTypePlainText": "Navadno besedilo",
"importTypeEnteEncrypted": "Ente šifriran izvoz",
"passwordForDecryptingExport": "Geslo za dešifriranje izvoza",
"passwordEmptyError": "Geslo ne sme biti prazno",
"importFromApp": "Uvozi kode iz {appName}",
"importGoogleAuthGuide": "Svoje račune iz Google Authenticatorja izvozite v kodo QR z možnostjo \"Prenos računov\" (en.: \"Transfer Accounts\"). Nato z drugo napravo preberite kodo QR.\n\nNasvet: Za slikanje kode QR lahko uporabite spletno kamero prenosnega računalnika.",
"importSelectJsonFile": "Izberi datoteko JSON",
"importSelectAppExport": "Izberi {appName} izvozno datoteko",
"importEnteEncGuide": "Izberi šifrirano JSON datoteko izvoženo iz Ente",
"importRaivoGuide": "Uporabite možnost \"Izvozi OTP v arhiv Zip\" (\"Export OTPs to Zip archive\") v nastavitvah Raivo.\n\nRazširite datoteko zip in uvozite datoteko JSON.",
"importBitwardenGuide": "V orodjih Bitwarden Tools uporabite možnost \"Izvozi trezor\" (\"Export vault\") in uvozite nešifrirano datoteko JSON.",
"importAegisGuide": "Uporabite možnost \"Izvozi trezor\" (\"Export the vault\") v nastavitvah aplikacije Aegis.\n\nČe je vaš trezor šifriran, boste morali vnesti geslo za dešifriranje trezorja.",
"import2FasGuide": "V programu 2FAS uporabite možnost \"Nastavitve ->Zaščitno kopiranje - Izvoz\" (\"Settings->Backup -Export\").\n\nČe je varnostna kopija šifrirana, boste morali vnesti geslo za dešifriranje varnostne kopije.",
"importLastpassGuide": "Uporabite možnost \"Prenos računov\" (\"Transfer accounts\") v nastavitvah Lastpass Authenticatorja in pritisnite \"Izvozi račune v datoteko\" (\"Export accounts to file\"). Nato uvozite preneseno datoteko JSON.",
"exportCodes": "Izvozi kode",
"importLabel": "Uvoz",
"importInstruction": "Izberite datoteko, ki vsebuje seznam vaših kod v naslednji obliki",
"importCodeDelimiterInfo": "Kode so lahko ločene z vejico ali novo vrstico.",
"selectFile": "Izberi datoteko",
"emailVerificationToggle": "Verifikacija e-pošte",
"emailVerificationEnableWarning": "Če se želite izogniti zaklepanju računa, pred omogočanjem preverjanja e-pošte shranite kopijo e-poštnega potrdila 2FA zunaj storitve Ente Auth.",
"authToChangeEmailVerificationSetting": "Za spremembo potrjevanja vašega naslova e-pošte, se overite",
"authenticateGeneric": "Prosimo. overite se",
"authToViewYourRecoveryKey": "Če si želite ogledati svoje ključ za obnovo, se overite",
"authToChangeYourEmail": "Za spremembo vašega naslova e-pošte, se overite",
"authToChangeYourPassword": "Za spremembo gesla, se overite",
"authToViewSecrets": "Če si želite ogledati svoje skrivne ključe, se overite",
"authToInitiateSignIn": "Za začetek prijave za varnostno kopiranje, se overite",
"ok": "V redu",
"cancel": "Prekliči",
"yes": "Da",
"no": "Ne",
"email": "E-pošta",
"support": "Podpora",
"general": "Splošno",
"settings": "Nastavitve",
"copied": "Kopirano",
"pleaseTryAgain": "Prosimo, poskusite ponovno",
"existingUser": "Obstoječ uporabnik",
"newUser": "Nov pri Ente",
"delete": "",
"enterYourPasswordHint": "Vnesite svoje geslo",
"forgotPassword": "Pozabljeno geslo",
"oops": "Ups",
"suggestFeatures": "Predlagaj funkcije",
"faq": "Pogosta vprašanja",
"somethingWentWrongMessage": "Nekaj je šlo narobe, prosimo poizkusite znova.",
"leaveFamily": "Zapusti družino",
"leaveFamilyMessage": "Ste prepričani, da želite zapustiti družinski paket?",
"inFamilyPlanMessage": "Ste na družinskem paketu!",
"hintForMobile": "Uredite ali izbrišite kodo z držanjem na njej.",
"hintForDesktop": "Uredite ali izbrišite kodo z desnim klikom na njo.",
"scan": "Skeniraj",
"scanACode": "Skeniraj kodo",
"verify": "Preveri",
"verifyEmail": "Potrdite e-pošto",
"enterCodeHint": "Vnesite 6 mestno kodo iz vaše aplikacije za preverjanje pristnosti",
"lostDeviceTitle": "Izgubljena naprava?",
"twoFactorAuthTitle": "Dvojno preverjanja pristnosti",
"passkeyAuthTitle": "Potrditev ključa za dostop (passkey)",
"verifyPasskey": "Potrdite ključ za dostop (passkey)",
"recoverAccount": "Obnovi račun",
"enterRecoveryKeyHint": "Vnesite vaš ključ za obnovitev",
"recover": "Obnovi",
"contactSupportViaEmailMessage": "Prosimo, pošljite e-pošto na {email} iz naslova s katerim ste registrirani",
"@contactSupportViaEmailMessage": {
"placeholders": {
"email": {
"type": "String"
}
}
},
"invalidQRCode": "Neveljavna QR koda",
"noRecoveryKeyTitle": "Nimate ključa za obnovo?",
"enterEmailHint": "Vnesite svoj e-poštni naslov",
"invalidEmailTitle": "Neveljaven e-poštni naslov",
"invalidEmailMessage": "Prosimo vnesite veljaven e-poštni naslov.",
"deleteAccount": "Izbriši račun",
"deleteAccountQuery": "Žal nam je, da odhajate. Imate kakšne težave?",
"yesSendFeedbackAction": "Ja, pošlji povratne informacije",
"noDeleteAccountAction": "Ne, izbriši račun",
"initiateAccountDeleteTitle": "Za izbris računa, se overite",
"sendEmail": "Pošlji e-pošto",
"createNewAccount": "Ustvari nov račun",
"weakStrength": "Šibko",
"strongStrength": "Močno",
"moderateStrength": "Zmerno",
"confirmPassword": "Potrdi geslo",
"close": "Zapri",
"oopsSomethingWentWrong": "Ups, nekaj je šlo narobe.",
"selectLanguage": "Izberi jezik",
"language": "Jezik",
"social": "Družabno",
"security": "Varnost",
"lockscreen": "Zaklenjen zaslon",
"authToChangeLockscreenSetting": "Za spremembo nastavitev zaklenjenega zaslona, se overite",
"deviceLockEnablePreSteps": "Da omogočite zaklepanje naprave, prosimo nastavite kodo ali zaklepanje zaslona v sistemskih nastavitvah.",
"viewActiveSessions": "Preglej aktivne seje",
"authToViewYourActiveSessions": "Če si želite ogledati svoje aktivne seje, se overite",
"searchHint": "Iskanje...",
"search": "Iskanje",
"sorryUnableToGenCode": "Oprostite, ni možno ustvariti kode za {issuerName}",
"noResult": "Ni rezultatov",
"addCode": "Dodaj kodo",
"scanAQrCode": "Skeniraj QR kodo",
"enterDetailsManually": "Vnesi podatke ročno",
"edit": "Uredi",
"share": "Deli",
"shareCodes": "Deli kode",
"shareCodesDuration": "Izberite trajanje, za katero želite deliti kode",
"restore": "Povrni",
"copiedToClipboard": "Kopirano v odložišče",
"copiedNextToClipboard": "Naslednja koda kopirana v odložišče",
"error": "Napaka",
"recoveryKeyCopiedToClipboard": "Ključ za obnovo kopiran v odložišče",
"recoveryKeyOnForgotPassword": "Če pozabite svoje geslo, je edini način da obnovite svoje podatke s tem ključem",
"recoveryKeySaveDescription": "Tega ključa ne hranimo, prosimo shranite teh 24 besed na varnem",
"doThisLater": "Stori to kasneje",
"saveKey": "Shrani ključ",
"save": "Shrani",
"send": "Pošlji",
"saveOrSendDescription": "Želite to shraniti v shrambo (privzeto: mapa Prenosi) ali poslati drugim aplikacijam?",
"saveOnlyDescription": "Želite to shraniti v shrambo (privzeto: mapa Prenosi)?",
"back": "Nazaj",
"createAccount": "Ustvari račun",
"passwordStrength": "Moč gesla: {passwordStrengthValue}",
"@passwordStrength": {
"description": "Text to indicate the password strength",
"placeholders": {
"passwordStrengthValue": {
"description": "The strength of the password as a string",
"type": "String",
"example": "Weak or Moderate or Strong"
}
},
"message": "Password Strength: {passwordStrengthText}"
},
"password": "Geslo",
"signUpTerms": "Strinjam se s <u-terms>pogoji uporabe</u-terms> in <u-policy>politiko zasebnosti</u-policy>",
"privacyPolicyTitle": "Politika zasebnosti",
"termsOfServicesTitle": "Pogoji uporabe",
"encryption": "Šifriranje",
"setPasswordTitle": "Nastavite geslo",
"changePasswordTitle": "Sprememba gesla",
"resetPasswordTitle": "Ponastavitev gesla",
"encryptionKeys": "Šifrirni ključi",
"passwordWarning": "Tega gesla ne shranjujemo, zato v primeru, da ga pozabite, <underline>ne moremo dešifrirati vaših podatkov</underline>.",
"enterPasswordToEncrypt": "Vnesite geslo, ki ga lahko uporabimo za šifriranje vaših podatkov",
"enterNewPasswordToEncrypt": "Vnesite novo geslo, ki ga lahko uporabimo za šifriranje vaših podatkov",
"passwordChangedSuccessfully": "Geslo je bilo uspešno spremenjeno",
"generatingEncryptionKeys": "Ustvarjanje ključe za šifriranje",
"continueLabel": "Nadaljuj",
"insecureDevice": "Nezanesljiva naprava",
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Žal v tej napravi nismo mogli ustvariti varnih ključev.\n\nProsimo, prijavite se iz druge naprave.",
"howItWorks": "Kako deluje? ",
"ackPasswordLostWarning": "Razumem, da lahko z izgubo gesla, izgubim svoje podatke, saj so <underline>end-to-end šifrirani</underline>",
"loginTerms": "S klikom na prijava, se strinjam s <u-terms>pogoji uporabe</u-terms> in <u-policy>politiko zasebnosti</u-policy>",
"logInLabel": "Prijava",
"logout": "Odjava",
"areYouSureYouWantToLogout": "Ali ste prepričani, da se želite odjaviti?",
"yesLogout": "Ja, odjavi se",
"exit": "Izhod",
"verifyingRecoveryKey": "Preverjanje ključa za obnovitev",
"recoveryKeyVerified": "Ključ za obnovitev preverjen",
"recoveryKeySuccessBody": "Odlično! Vaš ključ za obnovitev je veljaven. Hvala za preverjanje.\n\nNe pozabite shraniti varnostno kopijo obnovitvenega ključa.",
"invalidRecoveryKey": "Vneseni obnovitveni ključ ni veljaven. Prepričajte se, da vsebuje 24 besed, in preverite črkovanje vsake od njih.\n\nČe ste vnesli starejšo obnovitveno kodo, se prepričajte, da je dolga 64 znakov, in preverite vsakega od njih.",
"recreatePasswordTitle": "Ponovno ustvarite geslo",
"recreatePasswordBody": "Trenutna naprava, ni dovolj zmogljiva za preverjanje vašega gesla, a ga lahko generiramo na način, ki deluje z vsemi napravami.\n\nProsimo, prijavite se z vašim ključem za obnovo in ponovno ustvarite geslo (če želite lahko uporabite enako kot prej).",
"invalidKey": "Neveljaven ključ",
"tryAgain": "Poskusite ponovno",
"viewRecoveryKey": "Poglej ključ za obnovitev",
"confirmRecoveryKey": "Potrdi ključ za obnovitev",
"recoveryKeyVerifyReason": "Ključ za obnovitev je edini način za obnovitev fotografij, če pozabite geslo. Ključ za obnovitev najdete v razdelku Nastavitve > Račun.\n\nTukaj vnesite svoj obnovitveni ključ, da preverite, ali ste ga pravilno shranili.",
"confirmYourRecoveryKey": "Potrdite vaš ključ za obnovitev",
"confirm": "Potrdi",
"emailYourLogs": "Pošlji loge po e-pošti",
"pleaseSendTheLogsTo": "Loge pošljite na naslov \n{toEmail}",
"copyEmailAddress": "Kopiraj e-poštni naslov",
"exportLogs": "Izvozi loge",
"enterYourRecoveryKey": "Vnesite vaš ključ za obnovitev",
"tempErrorContactSupportIfPersists": "Zdi se, da je šlo nekaj narobe. Po določenem času poskusite znova. Če se napaka nadaljuje, se obrnite na našo ekipo za podporo.",
"networkHostLookUpErr": "Ne morete se povezati z Ente, preverite omrežne nastavitve in se obrnite na podporo, če se napaka nadaljuje.",
"networkConnectionRefusedErr": "Ne morete se povezati z Ente, poskusite znova čez nekaj časa. Če se napaka nadaljuje, se obrnite na podporo.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Zdi se, da je šlo nekaj narobe. Po določenem času poskusite znova. Če se napaka nadaljuje, se obrnite na našo ekipo za podporo.",
"about": "O nas",
"weAreOpenSource": "Smo odprto kodni!",
"privacy": "Zasebnost",
"terms": "Pogoji uporabe",
"checkForUpdates": "Preveri za posodobitve",
"checkStatus": "Preveri status",
"downloadUpdate": "Prenesi",
"criticalUpdateAvailable": "Nujna posodobitev je na voljo",
"updateAvailable": "Posodobitev je na voljo",
"update": "Posodobi",
"checking": "Preverjanje...",
"youAreOnTheLatestVersion": "Imate najnovejšo verzijo",
"warning": "Opozorilo",
"exportWarningDesc": "Izvožena datoteka vsebuje zasebne informacije. Prosimo, hranite jo na varnem.",
"iUnderStand": "Razumem",
"@iUnderStand": {
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Za izvoz kod, se overite",
"importSuccessTitle": "Juhu!",
"importSuccessDesc": "Uvozili ste {count} kod!",
"@importSuccessDesc": {
"placeholders": {
"count": {
"description": "The number of codes imported",
"type": "int",
"example": "1"
}
}
},
"sorry": "Oprostite",
"importFailureDesc": "Izbrane datoteke ni bilo možno prebrati. Če potrebujete pomoč, nam pišite na support@ente.io",
"pendingSyncs": "Opozorilo",
"pendingSyncsWarningBody": "Nekatere vaše kode niso varnostno kopirane.\n\nProsimo, prepričajte se, da so te kode varnostno kopirane preden se odjavite.",
"checkInboxAndSpamFolder": "Prosimo, preverite svoj e-poštni predal (in nezaželeno pošto), da končate verifikacijo",
"tapToEnterCode": "Pritisni za vnos kode",
"resendEmail": "Ponovno pošlji e-pošto",
"weHaveSendEmailTo": "Poslali smo e-pošto na <green>{email}</green>",
"@weHaveSendEmailTo": {
"description": "Text to indicate that we have sent a mail to the user",
"placeholders": {
"email": {
"description": "The email address of the user",
"type": "String",
"example": "example@ente.io"
}
}
},
"activeSessions": "Aktivne seje",
"somethingWentWrongPleaseTryAgain": "Nekaj je šlo narobe, prosimo poizkusite znova.",
"thisWillLogYouOutOfThisDevice": "To vas bo odjavilo iz te naprave!",
"thisWillLogYouOutOfTheFollowingDevice": "To vas bo odjavilo iz naslednje naprave:",
"terminateSession": "Končaj sejo",
"terminate": "Končaj",
"thisDevice": "Ta naprava",
"toResetVerifyEmail": "Če želite ponastaviti geslo, najprej potrdite svoj e-poštni naslov.",
"thisEmailIsAlreadyInUse": "Ta e-poštni naslove je že v uporabi.",
"verificationFailedPleaseTryAgain": "Potrjevanje ni bilo uspešno, prosimo poskusite znova.",
"yourVerificationCodeHasExpired": "Vaša koda za potrditev je potekla.",
"incorrectCode": "Nepravilna koda",
"sorryTheCodeYouveEnteredIsIncorrect": "Oprostite, koda ki ste jo vnesli ni pravilna",
"emailChangedTo": "E-poštni naslove je bil spremenjen na {newEmail}",
"authenticationFailedPleaseTryAgain": "Overitev ni uspela, prosimo poskusite znova",
"authenticationSuccessful": "Overitev uspešna!",
"twofactorAuthenticationSuccessfullyReset": "Uspešna ponastavitev dvostopenjske avtentikacije",
"incorrectRecoveryKey": "Nepravilen ključ za obnovitev",
"theRecoveryKeyYouEnteredIsIncorrect": "Ključ za obnovitev, ki ste ga vnesli ni pravilen",
"enterPassword": "Vnesite geslo",
"selectExportFormat": "Izberite obliko izvoza",
"exportDialogDesc": "Šifrirani izvozi bodo varovani z geslom po vaši izbiri.",
"encrypted": "Šifrirano",
"plainText": "Navadno besedilo",
"passwordToEncryptExport": "Geslo za šifriranje izvoza",
"export": "Izvoz",
"useOffline": "Uporabljal brez varnostnih kopij",
"signInToBackup": "Prijavite se za varnostno kopiranje kod",
"singIn": "Prijava",
"sigInBackupReminder": "Izvozite svoje kode in si zagotovite varnostno kopijo, iz katere lahko obnovite.",
"offlineModeWarning": "Odločili ste se, da boste nadaljevali brez varnostnih kopij. Prosimo, da naredite ročne varnostne kopije in se prepričajte, da so vaše kode varne.",
"showLargeIcons": "Prikaži velike ikone",
"compactMode": "Kompaktni način",
"shouldHideCode": "Skrij kode",
"doubleTapToViewHiddenCode": "Dvakrat kliknite vnos, da si ogledate kodo.",
"focusOnSearchBar": "Osredotočite iskanje ob zagonu aplikacije",
"confirmUpdatingkey": "Ali ste prepričani, da želite posodobiti skrivni ključ?",
"minimizeAppOnCopy": "Ob kopiranju, minimiziraj aplikacijo",
"editCodeAuthMessage": "Za urejanje kod, se overite",
"deleteCodeAuthMessage": "Za brisanje kod, se overite",
"showQRAuthMessage": "Da prikažete QR kodo, se overite",
"confirmAccountDeleteTitle": "Potrdi brisanje računa",
"confirmAccountDeleteMessage": "Ta račun je povezan z drugimi aplikacijami Ente, če jih uporabljate.\n\nVaši naloženi podatki v vseh aplikacijah Ente bodo načrtovane za izbris, vaš račun pa bo trajno izbrisan.",
"androidBiometricHint": "Potrdite identiteto",
"@androidBiometricHint": {
"description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters."
},
"androidBiometricNotRecognized": "Ni prepoznano. Poskusite znova.",
"@androidBiometricNotRecognized": {
"description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters."
},
"androidBiometricSuccess": "Uspešno",
"@androidBiometricSuccess": {
"description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters."
},
"androidCancelButton": "Prekliči",
"@androidCancelButton": {
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters."
},
"androidSignInTitle": "Potrebna je overitev",
"@androidSignInTitle": {
"description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters."
},
"androidBiometricRequiredTitle": "Zahtevani biometrični podatki",
"@androidBiometricRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsRequiredTitle": "Zahtevani podatki za vpis v napravo",
"@androidDeviceCredentialsRequiredTitle": {
"description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters."
},
"androidDeviceCredentialsSetupDescription": "Zahtevani podatki za vpis v napravo",
"@androidDeviceCredentialsSetupDescription": {
"description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side."
},
"goToSettings": "Pojdi v nastavitve",
"@goToSettings": {
"description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters."
},
"androidGoToSettingsDescription": "Biometrično overjanje v vaši napravi ni nastavljeno. Pojdite v \"Nastavitve > Varnost\" in dodajte biometrično overjanje.",
"@androidGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side."
},
"iOSLockOut": "Biometrično overjanje je onemogočeno. Če ga želite omogočiti, zaklenite in odklenite zaslon.",
"@iOSLockOut": {
"description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side."
},
"iOSGoToSettingsDescription": "Biometrično overjanje v vaši napravi ni nastavljeno. V telefonu omogočite funkcijo Touch ID ali Face ID.",
"@iOSGoToSettingsDescription": {
"description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side."
},
"iOSOkButton": "V redu",
"@iOSOkButton": {
"description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters."
},
"noInternetConnection": "Ni internetne povezave",
"pleaseCheckYourInternetConnectionAndTryAgain": "Preverite internetno povezavo in poskusite znova.",
"signOutFromOtherDevices": "Odjavi se iz ostalih naprav",
"signOutOtherBody": "Če menite, da bi lahko kdo poznal vaše geslo, lahko vse druge naprave, ki uporabljajo vaš račun, prisilite, da se odjavijo.",
"signOutOtherDevices": "Odjavi ostale naprave",
"doNotSignOut": "Ne odjavi se",
"hearUsWhereTitle": "Kako ste slišali o Ente? (izbirno)",
"hearUsExplanation": "Namestitvam aplikacij ne sledimo. Pomagalo bi, če bi nam povedali, kje ste nas našli!",
"recoveryKeySaved": "Ključ za obnovitev je shranjen v mapi Prenosi!",
"waitingForBrowserRequest": "Čakanje na zahtevo brskalnika...",
"waitingForVerification": "Čakanje na potrditev...",
"passkey": "Passkey",
"passKeyPendingVerification": "Preverjanje še ni zaključeno",
"loginSessionExpired": "Seja je potekla",
"loginSessionExpiredDetails": "Vaša seja je potekla. Prosimo ponovno se prijavite.",
"developerSettingsWarning": "Ste prepričani, da želite spremeniti nastavitve za razvijalce.",
"developerSettings": "Nastavitve za razvijalce",
"serverEndpoint": "Endpoint strežnika",
"invalidEndpoint": "Nepravilen endpoint",
"invalidEndpointMessage": "Oprostite endpoint, ki ste ga vnesli ni bil pravilen. Prosimo, vnesite pravilen endpoint in poskusite znova.",
"endpointUpdatedMessage": "Endpoint posodobljen uspešno",
"customEndpoint": "Povezano na {endpoint}",
"pinText": "Pripni",
"unpinText": "Odpni",
"pinnedCodeMessage": "{code} je bila pripeta",
"unpinnedCodeMessage": "{code} je bila odpeta",
"tags": "Oznake",
"createNewTag": "Ustvari novo oznako",
"tag": "Oznaka",
"create": "Ustvari",
"editTag": "Uredi oznako",
"deleteTagTitle": "Izbriši oznako?",
"deleteTagMessage": "Ali ste prepričani, da želite izbrisati to oznako? To dejanje je nepovratno.",
"somethingWentWrongParsingCode": "Nismo mogli prebrati {x} kod.",
"updateNotAvailable": "Posodobitev ni na voljo",
"viewRawCodes": "Poglej neobdelane kode",
"rawCodes": "Neobdelane kode",
"rawCodeData": "Podatki neobdelanih kod",
"appLock": "Zaklep aplikacije",
"noSystemLockFound": "Nobeno zaklepanje sistema ni bilo najdeno",
"toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Da omogočite zaklepanje aplikacije, prosimo nastavite kodo ali zaklepanje zaslona v sistemskih nastavitvah.",
"autoLock": "Samodejno zaklepanje",
"immediately": "Takoj",
"reEnterPassword": "Ponovno vnesite geslo",
"reEnterPin": "Ponovno vnesite PIN",
"next": "Naprej",
"tooManyIncorrectAttempts": "Preveč nepravilnih poskusov",
"tapToUnlock": "Kliknite za odklepanje",
"setNewPassword": "Nastavi novo geslo",
"deviceLock": "Zaklepanje naprave",
"hideContent": "Skrij vsebino",
"hideContentDescriptionAndroid": "Skrije vsebino aplikacije v menjalniku opravil in onemogoči posnetke zaslona",
"hideContentDescriptioniOS": "Skrije vsebino aplikacije v menjalniku opravil",
"autoLockFeatureDescription": "Čas po katerem se aplikacije zaklene, ko jo enkrat zapustite.",
"appLockDescription": "Izbirate lahko med privzetim zaklenjenim zaslonom naprave in zaklenjenim zaslonom po meri s kodo PIN ali geslom.",
"pinLock": "Zaklepanje s PIN",
"enterPin": "Vnesi PIN",
"setNewPin": "Nastavi nov PIN",
"importFailureDescNew": "Izbrane datoteke ni bilo mogoče prebrati",
"appLockNotEnabled": "Zaklepanje aplikacije ni omogočeno",
"appLockNotEnabledDescription": "Prosimo, omogočite zaklepanje aplikacije v Nastavitve > Zaklepanje Aplikacije (Security > App Lock)",
"authToViewPasskey": "Da vidite passkey, se overite",
"appLockOfflineModeWarning": "Odločili ste se, da boste nadaljevali brez varnostnih kopij. Če boste pozabili geslo za odklepanje aplikacije, bo dostop do vaših podatkov onemogočen."
}

View File

@@ -216,7 +216,7 @@
"saveKey": "Зберегти ключ",
"save": "Зберегти",
"send": "Надіслати",
"saveOrSendDescription": "Чи хочете Ви зберегти це до свого сховища (тека Downloads за замовчуванням), чи надіслати його в інші додатки?",
"saveOrSendDescription": "Чи хочете ви зберегти це до свого сховища (типово тека Downloads), чи надіслати його в інші застосунки?",
"saveOnlyDescription": "Чи хочете Ви зберегти це до свого сховища (тека Downloads за замовчуванням)?",
"back": "Назад",
"createAccount": "Створити обліковий запис",
@@ -279,8 +279,8 @@
"networkHostLookUpErr": "Не вдалося приєднатися до Ente. Будь ласка, перевірте налаштування мережі. Зверніться до нашої команди підтримки, якщо помилка залишиться.",
"networkConnectionRefusedErr": "Не вдалося приєднатися до Ente. Будь ласка, спробуйте ще раз через деякий час. Якщо помилка не зникне, зв'яжіться з нашою командою підтримки.",
"itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Схоже, що щось пішло не так. Будь ласка, спробуйте ще раз через деякий час. Якщо помилка не зникне, зв'яжіться з нашою командою підтримки.",
"about": "Про додаток",
"weAreOpenSource": "Наш додаток має відкритий код!",
"about": "Про застосунок",
"weAreOpenSource": "Наш застосунок має відкритий код!",
"privacy": "Конфіденційність",
"terms": "Умови",
"checkForUpdates": "Перевiрити наявнiсть оновлень",
@@ -359,7 +359,7 @@
"sigInBackupReminder": "Будь ласка, експортуйте свої коди, щоб зберегти резервну копію, з якої ви зможете їх відновити.",
"offlineModeWarning": "Ви збираєтеся продовжити без резервних копій. Будь ласка, зробіть ручну резервну копію, щоб переконатися, що ваші коди в безпеці.",
"showLargeIcons": "Показувати великі іконки",
"compactMode": "Компактний режим",
"compactMode": "Стислий режим",
"shouldHideCode": "Приховати коди",
"doubleTapToViewHiddenCode": "Ви можете двічі натиснути на запис для перегляду коду",
"focusOnSearchBar": "Сфокусуватися на пошуку після запуску програми",
@@ -429,7 +429,7 @@
"signOutOtherDevices": "Вийти на інших пристроях",
"doNotSignOut": "Не виходити",
"hearUsWhereTitle": "Як ви дізналися про Ente? (опціонально)",
"hearUsExplanation": "Ми не відстежуємо встановлення додатків. Але, якщо ви скажете нам, де ви нас знайшли, це допоможе!",
"hearUsExplanation": "Ми не відстежуємо встановлення застосунків. Але, якщо ви скажете нам, де ви нас знайшли, це допоможе!",
"recoveryKeySaved": "Ключ відновлення збережений у теці Downloads!",
"waitingForBrowserRequest": "Очікування запиту браузера...",
"waitingForVerification": "Очікується підтвердження...",
@@ -472,10 +472,10 @@
"tapToUnlock": "Доторкніться, щоб розблокувати",
"setNewPassword": "Встановити новий пароль",
"deviceLock": "Блокування пристрою",
"hideContent": "Приховати зміст",
"hideContentDescriptionAndroid": "Приховує зміст програми в перемикачі програм і вимикає скриншоти",
"hideContentDescriptioniOS": "Приховує зміст в перемикачі додатків",
"autoLockFeatureDescription": "Час, через який додаток буде заблоковано після розміщення у фоновому режимі",
"hideContent": "Приховати вміст",
"hideContentDescriptionAndroid": "Приховує вміст програми у перемикачі застосунків і вимикає знімки екрану",
"hideContentDescriptioniOS": "Приховує вміст у перемикачі застосунків",
"autoLockFeatureDescription": "Час, через який застосунок буде заблоковано після розміщення у фоновому режимі",
"appLockDescription": "Виберіть між типовим екраном блокування вашого пристрою та власним екраном блокування з PIN-кодом або паролем.",
"pinLock": "PIN-код",
"enterPin": "Введіть PIN-код",
@@ -483,5 +483,6 @@
"importFailureDescNew": "Не вдалося обробити вибраний файл.",
"appLockNotEnabled": "Блокування програм не увімкнено",
"appLockNotEnabledDescription": "Увімкніть блокування програм від безпеки > Блокування програм",
"authToViewPasskey": "Будь ласка, авторизуйтеся для перегляду ключа доступу"
"authToViewPasskey": "Будь ласка, авторизуйтеся для перегляду ключа доступу",
"appLockOfflineModeWarning": "Ви обрали продовжити без резервних копій. Якщо ви забудете свій пароль, доступ до ваших даних буде заблоковано."
}

View File

@@ -483,5 +483,6 @@
"importFailureDescNew": "无法解析选定的文件。",
"appLockNotEnabled": "应用锁未启用",
"appLockNotEnabledDescription": "请从“安全”>“应用锁”启用应用锁",
"authToViewPasskey": "请验证身份以查看通行密钥"
"authToViewPasskey": "请验证身份以查看通行密钥",
"appLockOfflineModeWarning": "您已选择继续而不备份。如果您忘记了应用锁,您将无法访问数据。"
}

View File

@@ -7,7 +7,6 @@ import 'package:ente_auth/core/configuration.dart';
import 'package:ente_auth/core/constants.dart';
import 'package:ente_auth/core/logging/super_logging.dart';
import 'package:ente_auth/core/network.dart';
import 'package:ente_auth/core/win_http_client.dart';
import 'package:ente_auth/ente_theme_data.dart';
import 'package:ente_auth/locale.dart';
import 'package:ente_auth/services/authenticator_service.dart';
@@ -65,9 +64,6 @@ Future<void> initSystemTray() async {
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isWindows) {
HttpOverrides.global = WindowsHttpOverrides();
}
if (PlatformUtil.isDesktop()) {
await windowManager.ensureInitialized();

View File

@@ -17,6 +17,7 @@ class IconUtils {
final Map<String, CustomIconData> _customIcons = {};
// Map of icon-color to its luminance
final Map<Color, double> _colorLuminance = {};
final List<String> _titleSplitCharacters = ['(', '.'];
Future<void> init() async {
await _loadJson();
@@ -27,31 +28,36 @@ class IconUtils {
String provider, {
double width = 24,
}) {
final title = _getProviderTitle(provider);
if (_customIcons.containsKey(title)) {
return _getSVGIcon(
"assets/custom-icons/icons/${_customIcons[title]!.slug ?? title}.svg",
title,
_customIcons[title]!.color,
width,
context,
);
} else if (_simpleIcons.containsKey(title)) {
return _getSVGIcon(
"assets/simple-icons/icons/$title.svg",
title,
_simpleIcons[title],
width,
context,
);
} else if (title.isNotEmpty) {
final providerTitle = _getProviderTitle(provider);
final List<String> titlesList = [providerTitle];
titlesList.addAll(_titleSplitCharacters.where((char) => providerTitle.contains(char)).map((char) => providerTitle.split(char)[0]));
for(final title in titlesList){
if (_customIcons.containsKey(title)) {
return _getSVGIcon(
"assets/custom-icons/icons/${_customIcons[title]!.slug ?? title}.svg",
title,
_customIcons[title]!.color,
width,
context,
);
} else if (_simpleIcons.containsKey(title)) {
return _getSVGIcon(
"assets/simple-icons/icons/$title.svg",
title,
_simpleIcons[title],
width,
context,
);
}
}
if (providerTitle.isNotEmpty) {
bool showLargeIcon = width > 24;
return CircleAvatar(
radius: width / 2,
backgroundColor: getEnteColorScheme(context).avatarColors[
title.hashCode % getEnteColorScheme(context).avatarColors.length],
providerTitle.hashCode % getEnteColorScheme(context).avatarColors.length],
child: Text(
title.toUpperCase()[0],
providerTitle.toUpperCase()[0],
// fixed color
style: showLargeIcon
? getEnteTextTheme(context).h3Bold.copyWith(color: Colors.white)
@@ -131,7 +137,9 @@ class IconUtils {
);
if (icon["altNames"] != null) {
for (final name in icon["altNames"]) {
_customIcons[name] = CustomIconData(
_customIcons[name.toString()
.replaceAll(' ', '')
.toLowerCase()] = CustomIconData(
icon["slug"],
icon["hex"],
);
@@ -144,7 +152,7 @@ class IconUtils {
}
String _getProviderTitle(String provider) {
return provider.split(RegExp(r'[.(]'))[0].replaceAll(' ', '').toLowerCase();
return provider.replaceAll(' ', '').toLowerCase();
}
}

View File

@@ -5,6 +5,10 @@
#include <gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication
@@ -38,6 +42,7 @@ static void my_application_activate(GApplication *application)
// If running on Wayland assume the header bar will work (may need changing
// if future cases occur).
gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11
GdkScreen *screen = gtk_window_get_screen(window);
if (GDK_IS_X11_SCREEN(screen))
@@ -49,6 +54,21 @@ static void my_application_activate(GApplication *application)
}
}
#endif
#ifdef GDK_WINDOWING_WAYLAND
GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET(window));
if (GDK_IS_WAYLAND_DISPLAY(display)) {
// Check the XDG_CURRENT_DESKTOP environment variable to determine the
// desktop environment.
const gchar* current_desktop = g_getenv("XDG_CURRENT_DESKTOP");
if (current_desktop != NULL && g_str_has_prefix(current_desktop, "GNOME")) {
use_header_bar = TRUE;
} else {
use_header_bar = FALSE;
}
}
#endif
if (use_header_bar)
{
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
@@ -140,6 +160,12 @@ static void my_application_init(MyApplication *self) {}
MyApplication *my_application_new()
{
// Set the program name to the application ID, which helps various systems
// like GTK and desktop environments map this running application to its
// corresponding .desktop file. This ensures better integration by allowing
// the application to be recognized beyond its binary name.
g_set_prgname(APPLICATION_ID);
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
"flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,

View File

@@ -3,6 +3,7 @@
## v1.7.6 (Unreleased)
- Parse description from metadata JSON.
- Support Italian and Lithuanian translations.
- .
## v1.7.5

View File

@@ -153,6 +153,8 @@ const modelPathDownloadingIfNeeded = async (
) => {
const modelPath = modelSavePath(modelName);
await cleanupOldModelsIfNeeded();
if (!existsSync(modelPath)) {
log.info("CLIP image model not found, downloading");
await downloadModel(modelPath, modelName);
@@ -169,6 +171,33 @@ const modelPathDownloadingIfNeeded = async (
return modelPath;
};
/**
* Cleanup old models.
*
* This code runs whenever we need to download a new model, which usually
* happens when we update a model, so this is a great time to go through the
* list of previously existent but now unused models, and delete them if they
* exist to clean up the user's disk space.
*/
const cleanupOldModelsIfNeeded = async () => {
const oldModelNames = [
"clip-image-vit-32-float32.onnx",
"clip-text-vit-32-uint8.onnx",
"mobileclip_s2_image.onnx",
"mobileclip_s2_image_opset18_rgba_sim.onnx",
"mobileclip_s2_text_int32.onnx",
"yolov5s_face_640_640_dynamic.onnx",
];
for (const modelName of oldModelNames) {
const modelPath = modelSavePath(modelName);
if (existsSync(modelPath)) {
log.info(`Removing unused ML model at ${modelPath}`);
await fs.rm(modelPath);
}
}
};
/** Return the path where the given {@link modelName} is meant to be saved */
const modelSavePath = (modelName: string) =>
path.join(userDataPath(), "models", modelName);
@@ -202,8 +231,8 @@ const createInferenceSession = async (modelPath: string) => {
};
const cachedCLIPImageSession = makeCachedInferenceSession(
"mobileclip_s2_image_opset18_rgba_sim.onnx",
143093992 /* 143 MB */,
"mobileclip_s2_image_opset18_rgba_opt.onnx",
143099752 /* 143 MB */,
);
/**
@@ -228,8 +257,8 @@ export const computeCLIPImageEmbedding = async (
};
const cachedCLIPTextSession = makeCachedInferenceSession(
"mobileclip_s2_text_int32.onnx",
253895600 /* 253 MB */,
"mobileclip_s2_text_opset18_quant.onnx",
67144712 /* 67 MB */,
);
let _tokenizer: Tokenizer | undefined;
@@ -273,17 +302,21 @@ export const computeCLIPTextEmbeddingIfAvailable = async (text: string) => {
};
const cachedFaceDetectionSession = makeCachedInferenceSession(
"yolov5s_face_640_640_dynamic.onnx",
30762872 /* 29 MB */,
"yolov5s_face_opset18_rgba_opt.onnx",
28952612 /* 29 MB */,
);
/**
* Face detection with the YOLO model and ONNX runtime.
*/
export const detectFaces = async (input: Float32Array) => {
export const detectFaces = async (
input: Uint8ClampedArray,
inputShape: number[],
) => {
const session = await cachedFaceDetectionSession();
const inputArray = new Uint8Array(input.buffer);
const feeds = {
input: new ort.Tensor("float32", input, [1, 3, 640, 640]),
input: new ort.Tensor("uint8", inputArray, inputShape),
};
const t = Date.now();
const results = await session.run(feeds);

View File

@@ -109,6 +109,7 @@ export const sidebar = [
collapsed: true,
items: [
{ text: "General", link: "/photos/faq/general" },
{ text: "Installation", link: "/photos/faq/installing" },
{
text: "Export",
link: "/photos/faq/export",
@@ -172,6 +173,7 @@ export const sidebar = [
collapsed: true,
items: [
{ text: "General", link: "/auth/faq/" },
{ text: "Installation", link: "/auth/faq/installing" },
{
text: "Enteception",
link: "/auth/faq/enteception/",

View File

@@ -7,13 +7,14 @@ description: Frequently asked questions about Ente Auth
### How secure is Ente Auth?
All codes you backup via Ente is stored end-to-end encrypted. This means only
you can access your codes. Our apps are open source and our cryptography has
been externally audited.
All codes you backup via Ente is stored with end-to-end encryption. This means
only you can access your codes. Our apps are open source and our cryptography
has been externally audited.
### How can I delete or edit codes?
You can delete or edit a code long press (or right click on desktop) on that item.
You can delete or edit a code by long pressing (or right clicking on desktop) on
that item.
### How can I support this project?
@@ -24,40 +25,43 @@ at [ente.io](https://ente.io).
You can enable FaceID lock under Settings → Security → Lockscreen.
### Why does the desktop and mobile app displays different code?
### Why do the desktop and mobile apps display different codes?
Please verify that the time on both your mobile and desktop is same.
Please verify that the time on both your mobile and desktop is the same.
The codes depend on time. If the time is the same on both browser and mobile,
the codes you see will be the same.
The codes depend on time. If the time is the same on both your browser and
mobile, the codes you see will be the same.
Usually this discrepancy occurs because the time in your browser might be
incorrect. In particular, multiple users who have reported that Firefox provides
incorrect time when various privacy settings are enabled.
Usually, this discrepancy occurs because the time in your browser might be
incorrect. In particular, multiple users have reported that Firefox provides
incorrect time when certain privacy settings are enabled.
### Can I access my codes on web?
You can access your codes on the web at [auth.ente.io](https://auth.ente.io).
### Does Ente Authenticator require an account?
### Does Ente Auth require an account?
Answer: No, Ente Authenticator does not require an account. You can choose to
use the app without backups if you prefer.
No, Ente Auth does not require an account. You can choose to use the app without
backups if you prefer.
### Can I use the Ente 2FA app on multiple devices and sync them?
### Can I use Ente Auth on multiple devices and sync them?
Yes, you can download the Ente app on multiple devices and sync the codes,
end-to-end encrypted.
Yes, you can download Ente Auth on multiple devices and sync the codes with
end-to-end encryption.
### What information about my codes is stored on Ente server?
Due to E2EE, the server doesn't know anything about the code. Everything is encrypted, including the tags, type, account, issuer, notes, and pinned or trash status, etc."
Due to E2EE, the server doesn't know anything about your codes. Everything is
encrypted, including the tags, type, account, issuer, notes, pinned or trash
status, etc.
### What does it mean when I receive a message saying my current device is not powerful enough to verify my password?
### What does it mean when I receive a message saying that my current device isn't powerful enough to verify my password?
This means that the parameters that were used to derive your master-key on your
original device, are incompatible with your current device (likely because it's
less powerful).
If you recover your account via your current device and reset the password, it
will re-generate a key that will be compatible on both devices.
If you recover your account using your current device and reset the password, a
new key will be generated with different parameters. This new key will be
equally strong and compatible with both devices.

View File

@@ -0,0 +1,92 @@
---
title: Installing Ente Auth
description: Steps to install Ente Auth
---
# Android
Our Android apps are distributed over the following channels.
### PlayStore
You can install Auth directly from
[PlayStore](https://play.google.com/store/apps/details?id=io.ente.auth).
### F-Droid
Reproducible builds for Auth are available on
[F-Droid](https://f-droid.org/packages/io.ente.auth/).
> [!NOTE]
>
> Releases over F-Droid are generally slower since they run their own build
> servers. You can donate to F-Droid [here](https://f-droid.org/en/donate).
### GitHub
Latest releases are built straight from the source and made available over
[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4).
These builds will notify you whenever a new release is available and will help
you stay updated.
### Obtainium
You can setup [Obtainium](https://github.com/ImranR98/Obtainium) to track our
GitHub releases by [clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.auth.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Auth%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-auth*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D) to add it instantly.
Alternatively, you can follow these steps:
1. Click **Add App** to open a new app config screen
2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field
3. Enable the **Retain release order** from API toggle
4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-auth*`
5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle
6. Select any applicable app category labels you may have setup
7. Enable the **Try inferring app ID from source code** toggle
8. Scroll back to the top and click **Add** to complete the setup
<br/>
---
<br/>
# iOS
You can install Ente Auth on Apple devices from
[AppStore](https://apps.apple.com/us/app/ente-auth/id6444121398).
<br/>
---
<br/>
# Desktop
You can grab the latest version of Ente Auth for Mac, Windows and Linux from
[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4).
<br/>
---
<br/>
# Web
Latest versions of our web app are available at [auth.ente.io](https://auth.ente.io).
<br/>
---
<br/>
# CLI
Ente's CLI is distributed directly over
[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0).

View File

@@ -212,7 +212,7 @@ If this didn't work, refer to
1. Open Ente Authenticator on your phone
2. Log in to your account (if you haven't already), or press "Use without
backups".
backups".
3. Click the add button in the bottom right of the app.
4. Select "Scan a QR code" and scan the code from the browser.

View File

@@ -0,0 +1,92 @@
---
title: Installing Ente Photos
description: Steps to install Ente Photos
---
# Android
Our Android apps are distributed over the following channels.
### PlayStore
You can install Ente directly from
[PlayStore](https://play.google.com/store/apps/details?id=io.ente.photos).
### F-Droid
Reproducible builds for Ente are available on
[F-Droid](https://f-droid.org/packages/io.ente.photos.fdroid/).
> [!NOTE]
>
> Releases over F-Droid are generally slower since they run their own build
> servers. You can donate to F-Droid [here](https://f-droid.org/en/donate).
### GitHub
Latest releases are built straight from the source and made available over
[GitHub](https://github.com/ente-io/ente/releases?q=tag%253Aphotos-v0).
These builds will notify you whenever a new release is available and will help
you stay updated.
### Obtainium
You can setup [Obtainium](https://github.com/ImranR98/Obtainium) to track our
GitHub releases by [clicking this link](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.ente.photos.independent%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2Fente-io%2Fente%22%2C%22author%22%3A%22ente-io%22%2C%22name%22%3A%22Ente%20Photos%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Atrue%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22releaseTitleAsVersion%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22ente-photos*%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22allowInsecure%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D) to add it instantly.
Alternatively, you can follow these steps:
1. Click **Add App** to open a new app config screen
2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field
3. Enable the **Retain release order** from API toggle
4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-photos*`
5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle
6. Select any applicable app category labels you may have setup
7. Enable the **Try inferring app ID from source code** toggle
8. Scroll back to the top and click **Add** to complete the setup
<br/>
---
<br/>
# iOS
You can install Ente on Apple devices from
[AppStore](https://apps.apple.com/app/id1542026904).
<br/>
---
<br/>
# Desktop
You can grab the latest version of Ente for Mac, Windows and Linux from
[ente.io/download/desktop](https://ente.io/download/desktop).
<br/>
---
<br/>
# Web
Latest versions of our web app are available at [web.ente.io](https://web.ente.io).
<br/>
---
<br/>
# CLI
Ente's CLI is distributed directly over
[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0).

View File

@@ -71,6 +71,23 @@ not modify the original.
> functionality within the app itself) for customers who intentionally wish to
> modify their originals to reflect the associated metadata JSON.
As an example: suppose you have `flower.png`. When you export your library, you
will end up with:
```
flower.png
metadata/flower.png.json
```
Ente writes this JSON in the same format as Google Takeout so that if a tool
supports Google Takeout import, it should be able to read the JSON written by
Ente too
> One small difference is that, to avoid clutter, Ente puts the JSON in the
> `metadata/` subfolder, while Google puts it next to the file.<br>
>
> <br>Ente itself will read it from either place.
### File creation time.
The photo's data will be preserved verbatim, however when it is written out to

View File

@@ -26,3 +26,10 @@ browser APIs instead of going via the file system.
Note that the app will detect and skip over already uploaded items into an
album, so dragging and dropping the same folder again to upload to the same
album is fine.
> The underlying reason for this crash seeems to be the
> [4GB RAM usage limit for Electron apps](https://www.electronjs.org/blog/v8-memory-cage).
> We try to upload large videos by streaming them instead of reading them all in
> at once, but in some cases, even the streaming them seems to exceed the 4GB
> limit. We're trying to understand when this happens a bit more precisely, and
> if required, reimplement our uploads in a different way to avoid these.

View File

@@ -16,7 +16,11 @@ the same code we use for our own cloud service.
## Getting started
Start the server
#### Installing Docker
Refer to [How to install Docker from the APT repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository) for detailed instructions.
#### Start the server
```sh
git clone https://github.com/ente-io/ente
@@ -29,6 +33,16 @@ docker compose up --build
> You can also use a pre-built Docker image from `ghcr.io/ente-io/server`
> ([More info](https://github.com/ente-io/ente/blob/main/server/docs/docker.md))
Install the necessary dependencies for running the web client
```sh
# installing npm and yarn
sudo apt update
sudo apt install nodejs npm
sudo npm install -g yarn // to install yarn globally
```
Then in a separate terminal, you can run (e.g) the web client
```sh

22
infra/ml/.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv
# Models
*/onnx_models/
*.pt
*.onnx
*.tflite
# Imported repos
CLIP/mobileclip_repo/
# Data
data/flickr8k_captions.txt

1
infra/ml/.python-version Normal file
View File

@@ -0,0 +1 @@
3.12

File diff suppressed because it is too large Load Diff

19
infra/ml/README.md Normal file
View File

@@ -0,0 +1,19 @@
# Ente ML playground
This is a central place to keep track of any (Python) code used for prepping our ML models. The purpose of storing it here is to have some kind of version control over the alterations made to the models.
Most of the code is in [Jupyter Notebooks](https://jupyter.org/), which facilitates quick interation and good documentation.
## Running any notebook
In case you're using VSCode, make sure you've installed the [Jupyter](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter) extension and only have a [single window](https://github.com/microsoft/vscode/issues/125993#issuecomment-2099627960) open.
1. [Install uv](https://docs.astral.sh/uv/getting-started/installation/)
2. Run `uv sync`
3. Run `uv venv`
4. In any notebook, make sure to select the virtual environment kernel from `.venv/bin/python` in the top (right corner on VSCode)
## Notebooks and git
Please make sure to always clear output data inside a notebook before committing changes to git.
Jupyter notebooks are known to not always work nicely with Git versioning control when there is output in them.

View File

@@ -0,0 +1,999 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Prepping YOLOv5Face model for use in Ente\n",
"\n",
"[Paper](https://arxiv.org/abs/2105.12931) | [Github](https://github.com/deepcam-cn/yolov5-face)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setting up Pytorch weights and source code"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Please manually put the Pytorch .pt weights in the `pytorch_weights` directory. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"model_weights_path = \"pytorch_weights/yolov5s_face.pt\"\n",
"models_path = \"onnx_models/\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!mkdir yoloface_repo\n",
"%cd yoloface_repo\n",
"!git clone https://github.com/deepcam-cn/yolov5-face.git\n",
"%cd ..\n",
"!cp -r yoloface_repo/yolov5-face/models/ models/\n",
"!cp -r yoloface_repo/yolov5-face/utils/ utils/\n",
"!rm -rf yoloface_repo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Imports"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Libraries\n",
"import torch\n",
"import torch.nn as nn\n",
"from PIL import Image\n",
"import json\n",
"import numpy as np\n",
"import onnx\n",
"import onnxruntime as ort\n",
"print(ort.__version__)\n",
"\n",
"# Source code\n",
"from models.common import Conv, ShuffleV2Block\n",
"from models.experimental import attempt_load\n",
"from utils.activations import Hardswish, SiLU\n",
"from utils.general import set_logging, check_img_size"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Export to ONNX"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"onnx_opset = 18\n",
"img_size = [640, 640]\n",
"batch_size = 1\n",
"dynamic_shapes = False\n",
"\n",
"# Load PyTorch model\n",
"model = attempt_load(\n",
" model_weights_path, map_location=torch.device(\"cpu\")\n",
") # load FP32 model\n",
"delattr(model.model[-1], \"anchor_grid\")\n",
"model.model[-1].anchor_grid = [\n",
" torch.zeros(1)\n",
"] * 3 # nl=3 number of detection layers\n",
"model.model[-1].export_cat = True\n",
"model.eval()\n",
"labels = model.names\n",
"\n",
"# Checks\n",
"gs = int(max(model.stride)) # grid size (max stride)\n",
"img_size = [\n",
" check_img_size(x, gs) for x in img_size\n",
"] # verify img_size are gs-multiples\n",
"\n",
"# Test input\n",
"img = torch.zeros(batch_size, 3, *img_size)\n",
"\n",
"# Update model\n",
"for k, m in model.named_modules():\n",
" m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility\n",
" if isinstance(m, Conv): # assign export-friendly activations\n",
" if isinstance(m.act, nn.Hardswish):\n",
" m.act = Hardswish()\n",
" elif isinstance(m.act, nn.SiLU):\n",
" m.act = SiLU()\n",
" if isinstance(m, ShuffleV2Block): # shufflenet block nn.SiLU\n",
" for i in range(len(m.branch1)):\n",
" if isinstance(m.branch1[i], nn.SiLU):\n",
" m.branch1[i] = SiLU()\n",
" for i in range(len(m.branch2)):\n",
" if isinstance(m.branch2[i], nn.SiLU):\n",
" m.branch2[i] = SiLU()\n",
"y = model(img) # dry run\n",
"\n",
"# ONNX export\n",
"print(\"\\nStarting ONNX export with onnx %s...\" % onnx.__version__)\n",
"onnx_model_export_path = models_path + model_weights_path.replace(\".pt\", \".onnx\").split('/')[-1]\n",
"model.fuse() \n",
"input_names = [\"input\"]\n",
"output_names = [\"output\"]\n",
"torch.onnx.export(\n",
" model,\n",
" img,\n",
" onnx_model_export_path,\n",
" verbose=False,\n",
" opset_version=onnx_opset,\n",
" input_names=input_names,\n",
" output_names=output_names,\n",
" dynamic_axes=(\n",
" {\"input\": {0: \"batch\"}, \"output\": {0: \"batch\"}} if dynamic_shapes else None\n",
" ),\n",
")\n",
"\n",
"# Checks\n",
"onnx_model = onnx.load(onnx_model_export_path) # load onnx model\n",
"onnx.checker.check_model(onnx_model) # check onnx model\n",
"\n",
"# onnx infer\n",
"providers = [\"CPUExecutionProvider\"]\n",
"session = ort.InferenceSession(onnx_model_export_path, providers=providers)\n",
"im = img.cpu().numpy().astype(np.float32) # torch to numpy\n",
"y_onnx = session.run(\n",
" [session.get_outputs()[0].name], {session.get_inputs()[0].name: im}\n",
")[0]\n",
"print(\"pred's shape is \", y_onnx.shape)\n",
"print(\"max(|torch_pred - onnx_pred| =\", abs(y.cpu().numpy() - y_onnx).max())"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"!rm -rf models/\n",
"!rm -rf utils/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Altering ONNX model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Add preprocessing inside model"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from onnxruntime_extensions.tools.pre_post_processing import PrePostProcessor, create_named_value, Resize, ImageBytesToFloat, Unsqueeze, Debug, LetterBox, ChannelsLastToChannelsFirst"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"inputs = [create_named_value(\"input_to_preprocess\", onnx.TensorProto.UINT8, [\"H\", \"W\", \"C\"])]\n",
"\n",
"pipeline = PrePostProcessor(inputs, onnx_opset)\n",
"\n",
"pipeline.add_pre_processing(\n",
" [\n",
" Resize(640, layout= \"HWC\", policy=\"not_larger\"), # Resize to 640, maintaining aspect ratio and letting largest dimension not exceed 640 (so smaller dimension will be <= 640)\n",
" # Debug(),\n",
" LetterBox((640, 640), layout=\"HWC\", fill_value=114), # Add padding to make the image actually always 640x640,\n",
" ChannelsLastToChannelsFirst(), # Convert to CHW\n",
" # Debug(),\n",
" ImageBytesToFloat(), # Convert to float in range 0..1 by dividing uint8 values by 255\n",
" # Debug(),\n",
" Unsqueeze([0]), # add batch, CHW --> 1CHW\n",
" # Debug(),\n",
" ]\n",
")\n",
"\n",
"# pipeline.add_post_processing()\n",
"onnx_model_prepro = pipeline.run(onnx_model)\n",
"onnx.checker.check_model(onnx_model_prepro)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To debug and visually inspect the preprocessing, please uncomment the `Debug()` statements in above block and run it again, and then uncomment and run the code in the block below:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# onnx.save(onnx_model_prepro, \"yolov5s_face_prepro.onnx\")\n",
"\n",
"# image_singapore = Image.open(\"../data/singapore.jpg\").convert('RGB')\n",
"# image_singapore_onnx = np.array(image_singapore)\n",
"# print(image_singapore_onnx.shape)\n",
"# print(type(image_singapore_onnx))\n",
"# print(image_singapore_onnx.dtype)\n",
"\n",
"# ort_session = ort.InferenceSession(\"yolov5s_face_prepro.onnx\")\n",
"# test = ort_session.run(None, {\"input_to_preprocess\": image_singapore_onnx})\n",
"\n",
"# preprocessed = test[4]\n",
"# print(preprocessed.shape)\n",
"# print(type(preprocessed))\n",
"\n",
"# # import matplotlib#.pyplot as plt\n",
"# from IPython.display import display\n",
"# # matplotlib.use('TkAgg')\n",
"\n",
"# displayable_array = preprocessed.reshape(3, 640, 640).transpose((1, 2, 0))\n",
"# # Display the image\n",
"# # matplotlib.pyplot.imshow(displayable_array)\n",
"# # matplotlib.pyplot.axis('off') \n",
"# # matplotlib.pyplot.show()\n",
"# display(Image.fromarray((displayable_array * 255).astype(np.uint8)))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Add slice operator for use of RGBA input"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Create a new input with flexible channel dimension\n",
"new_input = onnx.helper.make_tensor_value_info(\n",
" name=\"input\",\n",
" elem_type=onnx.TensorProto.UINT8,\n",
" shape=[\"H\", \"W\", \"C\"], \n",
")\n",
"\n",
"# Create constant tensors for starts, ends, and axes and use them to create a Slice node\n",
"starts_tensor = onnx.helper.make_tensor(\n",
" name=\"starts\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([0], dtype=np.int64)\n",
")\n",
"ends_tensor = onnx.helper.make_tensor(\n",
" name=\"ends\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([3], dtype=np.int64)\n",
")\n",
"axes_tensor = onnx.helper.make_tensor(\n",
" name=\"axes\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([2], dtype=np.int64)\n",
")\n",
"slice_node = onnx.helper.make_node(\n",
" \"Slice\",\n",
" inputs=[\"input\", \"starts\", \"ends\", \"axes\"],\n",
" outputs=[\"sliced_input\"],\n",
" name=\"slice_rgba_input_node\",\n",
")\n",
"# Combine initializers\n",
"initializers = [starts_tensor, ends_tensor, axes_tensor] + list(onnx_model_prepro.graph.initializer)\n",
"\n",
"# Get the name of the original input\n",
"original_input_name = onnx_model_prepro.graph.input[0].name\n",
"\n",
"# Make new graph by adding the new input and Slice node to the old graph\n",
"graph = onnx.helper.make_graph(\n",
" [slice_node] + list(onnx_model_prepro.graph.node), # Prepend Slice node to existing nodes\n",
" onnx_model_prepro.graph.name,\n",
" [new_input] + list(onnx_model_prepro.graph.input)[1:], # Replace first input, keep others\n",
" list(onnx_model_prepro.graph.output),\n",
" initializer=initializers,\n",
" value_info=onnx_model_prepro.graph.value_info,\n",
")\n",
"\n",
"# Create the new model\n",
"onnx_model_rgba = onnx.helper.make_model(\n",
" graph,\n",
" opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n",
")\n",
"\n",
"# Update the input names in the rest of the model\n",
"for node in onnx_model_rgba.graph.node:\n",
" for i, input_name in enumerate(node.input):\n",
" if input_name == original_input_name:\n",
" node.input[i] = \"sliced_input\"\n",
"\n",
"# Save the new model\n",
"onnx.checker.check_model(onnx_model_rgba)\n",
"onnx_model_rgba_path = onnx_model_export_path[:-5] + \"_rgba.onnx\"\n",
"onnx.save(onnx_model_rgba, onnx_model_rgba_path)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n",
"# image_onnx = np.array(image)\n",
"# print(image_onnx.shape)\n",
"# print(type(image_onnx))\n",
"# print(image_onnx.dtype)\n",
"\n",
"# ort_session = ort.InferenceSession(\"yolov5s_face_rgba.onnx\")\n",
"# test = ort_session.run(None, {\"input\": image_onnx})\n",
"# print(test[0].shape)\n",
"# scores_output = test[0][:,:,4]\n",
"# print(f\"Highest score: {scores_output.max()}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Add post-processing inside the model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's first rename the output of the model so we can name the post-processed output as `output`.\n",
"Then we have to split `[1, 25200, 16]` into `[1, 25200, 4]`, `[1, 25200, 1]`, `[1, 25200, 11]` (i.e. `[1, detections, bbox]`, `[1, detections, score]`, `[1, detections, landmarks]`) named `boxes`, `scores`, `masks`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Add a Split operator at the end so that it be used with the SelectBestBoundingBoxesByNMS operator\n",
"num_det = 25200\n",
"graph = onnx_model_rgba.graph\n",
"\n",
"# Let's first rename the output of the model so we can name the post-processed output as `output`\n",
"for node in onnx_model_rgba.graph.node:\n",
" for i, output_name in enumerate(node.output):\n",
" if output_name == \"output\":\n",
" node.output[i] = \"og_output\"\n",
"og_output = onnx.helper.make_tensor_value_info(\n",
" name=\"og_output\",\n",
" elem_type=onnx.TensorProto.FLOAT,\n",
" shape=[1, num_det, 16], \n",
")\n",
"\n",
"# Create the split node\n",
"boxes_output = onnx.helper.make_tensor_value_info(\n",
" name=\"boxes_unsqueezed\",\n",
" elem_type=onnx.TensorProto.FLOAT,\n",
" shape=[1, num_det, 4], \n",
")\n",
"scores_output = onnx.helper.make_tensor_value_info(\n",
" name=\"scores_unsqueezed\",\n",
" elem_type=onnx.TensorProto.FLOAT,\n",
" shape=[1, num_det, 1], \n",
")\n",
"masks_output = onnx.helper.make_tensor_value_info(\n",
" name=\"masks_unsqueezed\",\n",
" elem_type=onnx.TensorProto.FLOAT,\n",
" shape=[1, num_det, 11], \n",
")\n",
"splits_tensor = onnx.helper.make_tensor(\n",
" name=\"splits\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[3],\n",
" vals=np.array([4, 1, 11], dtype=np.int64)\n",
")\n",
"split_node = onnx.helper.make_node(\n",
" \"Split\",\n",
" inputs=[\"og_output\", \"splits\"],\n",
" outputs=[\"boxes_unsqueezed\", \"scores_unsqueezed\", \"masks_unsqueezed\"],\n",
" name=\"split_og_output\",\n",
" axis=2,\n",
")\n",
"\n",
"# Combine initializers\n",
"initializers = list(graph.initializer) + [splits_tensor]\n",
"\n",
"# Make new graph by adding the new outputs and Split node to the old graph\n",
"graph = onnx.helper.make_graph(\n",
" list(graph.node) + [split_node], # Append split node to existing nodes\n",
" graph.name,\n",
" list(graph.input), \n",
" [boxes_output, scores_output, masks_output],\n",
" initializer=initializers,\n",
" value_info=graph.value_info,\n",
")\n",
"\n",
"# Create the new model\n",
"onnx_model_split = onnx.helper.make_model(\n",
" graph,\n",
" opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n",
")\n",
"\n",
"# Save the new model\n",
"onnx.checker.check_model(onnx_model_split)\n",
"onnx_model_split_path = onnx_model_export_path[:-5] + \"_split.onnx\"\n",
"onnx.save(onnx_model_split, onnx_model_split_path)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can run NMS on these splitted outputs using `NonMaxSuppression` operator"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"num_det = 25200\n",
"graph = onnx_model_split.graph\n",
"nodes = list(graph.node)\n",
"outputs = list(graph.output)\n",
"initializers = list(graph.initializer)\n",
"original_output = graph.output[0]\n",
"\n",
"# Create the Transpose node for the scores (since NMS requires the scores to be in the middle dimension for some reason)\n",
"transpose_node_score = onnx.helper.make_node(\n",
" \"Transpose\",\n",
" inputs=[\"scores_unsqueezed\"],\n",
" outputs=[\"scores_transposed\"],\n",
" name=\"transpose_scores\",\n",
" perm=[0, 2, 1],\n",
")\n",
"nodes.append(transpose_node_score)\n",
"\n",
"# Create the NMS node\n",
"nms_indices = onnx.helper.make_tensor_value_info(\"nms_indices\", onnx.TensorProto.INT64, shape=[\"detections\", 3])\n",
"max_output = onnx.helper.make_tensor(\"max_output\",onnx.TensorProto.INT64, [1], np.array([100], dtype=np.int64))\n",
"iou_threshold = onnx.helper.make_tensor(\"iou_threshold\",onnx.TensorProto.FLOAT, [1], np.array([0.4], dtype=np.float32))\n",
"score_threshold = onnx.helper.make_tensor(\"score_threshold\",onnx.TensorProto.FLOAT, [1], np.array([0.6], dtype=np.float32))\n",
"initializers = initializers + [max_output, iou_threshold, score_threshold]\n",
"nms_node = onnx.helper.make_node(\n",
" \"NonMaxSuppression\",\n",
" inputs=[\"boxes_unsqueezed\", \"scores_transposed\", \"max_output\", \"iou_threshold\", \"score_threshold\"],\n",
" outputs=[\"nms_indices\"],\n",
" name=\"perform_nms\",\n",
" center_point_box=1,\n",
")\n",
"nodes.append(nms_node)\n",
"outputs.append(nms_indices)\n",
"\n",
"# Make new graph by adding the new outputs and Split node to the old graph\n",
"graph = onnx.helper.make_graph(\n",
" nodes,\n",
" graph.name,\n",
" list(graph.input), \n",
" outputs,\n",
" initializer=initializers,\n",
" value_info=graph.value_info,\n",
")\n",
"\n",
"# Create the new model\n",
"onnx_model_nms = onnx.helper.make_model(\n",
" graph,\n",
" opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n",
")\n",
"\n",
"# Save the new model\n",
"onnx.checker.check_model(onnx_model_nms)\n",
"onnx_model_nms_path = onnx_model_export_path[:-5] + \"_nms.onnx\"\n",
"onnx.save(onnx_model_nms, onnx_model_nms_path)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n",
"# image_onnx = np.array(image)\n",
"\n",
"# ort_session = ort.InferenceSession(\"yolov5s_face_nms.onnx\")\n",
"# test = ort_session.run(None, {\"input\": image_onnx})\n",
"# print(test[3].shape)\n",
"# print(test[3])\n",
"# print(test[1][0, 24129, 0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we need to add some Squeeze, Slice and Gather nodes so handle the NMS given indices properly. The goal is that the final output is a very simple array of shape `(detections, 16)` of only the relevant detections."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"num_det = 25200\n",
"graph = onnx_model_nms.graph\n",
"nodes = list(graph.node)\n",
"outputs = list(graph.output)\n",
"initializers = list(graph.initializer)\n",
"original_output = graph.output[0]\n",
"\n",
"# Create Slide node to slice the NMS indices from (detections, 3) to (detections, 1) by taking the third column\n",
"sliced_indices = onnx.helper.make_tensor_value_info(\"sliced_indices\", onnx.TensorProto.INT64, shape=[\"detections\", 1])\n",
"outputs.append(sliced_indices)\n",
"starts_slice_tensor = onnx.helper.make_tensor(\n",
" name=\"starts_slice_tensor\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([2], dtype=np.int64)\n",
")\n",
"ends_slice_tensor = onnx.helper.make_tensor(\n",
" name=\"ends_slice_tensor\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([3], dtype=np.int64)\n",
")\n",
"axes_slice_tensor = onnx.helper.make_tensor(\n",
" name=\"axes_slice_tensor\",\n",
" data_type=onnx.TensorProto.INT64,\n",
" dims=[1],\n",
" vals=np.array([1], dtype=np.int64)\n",
")\n",
"initializers = initializers + [starts_slice_tensor, ends_slice_tensor, axes_slice_tensor]\n",
"slice_node = onnx.helper.make_node(\n",
" \"Slice\",\n",
" inputs=[\"nms_indices\", \"starts_slice_tensor\", \"ends_slice_tensor\", \"axes_slice_tensor\"],\n",
" outputs=[\"sliced_indices\"],\n",
" name=\"slice_nms_indices\",\n",
")\n",
"nodes.append(slice_node)\n",
"\n",
"# Create Squeeze node to squeeze the sliced indices\n",
"squeezed_indices = onnx.helper.make_tensor_value_info(\"squeezed_indices\", onnx.TensorProto.INT64, shape=[\"detections\"])\n",
"outputs.append(squeezed_indices)\n",
"squeeze_slice_tensor = onnx.helper.make_tensor(\"squeeze_slice_axis\",onnx.TensorProto.INT64, [1], np.array([1], dtype=np.int64))\n",
"initializers.append(squeeze_slice_tensor)\n",
"squeeze_slice_node = onnx.helper.make_node(\n",
" \"Squeeze\",\n",
" inputs=[\"sliced_indices\", \"squeeze_slice_axis\"],\n",
" outputs=[\"squeezed_indices\"],\n",
" name=\"squeeze_sliced_indices\",\n",
")\n",
"nodes.append(squeeze_slice_node)\n",
"\n",
"# Create Squeeze node to squeeze the original output\n",
"squeezed_output = onnx.helper.make_tensor_value_info(\"squeezed_output\", onnx.TensorProto.FLOAT, shape=[25200, 16])\n",
"outputs.append(squeezed_output)\n",
"squeeze_tensor = onnx.helper.make_tensor(\"squeeze_axis\",onnx.TensorProto.INT64, [1], np.array([0], dtype=np.int64))\n",
"initializers.append(squeeze_tensor)\n",
"squeeze_node = onnx.helper.make_node(\n",
" \"Squeeze\",\n",
" inputs=[\"og_output\", \"squeeze_axis\"],\n",
" outputs=[\"squeezed_output\"],\n",
" name=\"squeeze_output\",\n",
")\n",
"nodes.append(squeeze_node)\n",
"\n",
"\n",
"# Create Gather node to gather the relevant NMS indices from the original output\n",
"postpro_output = onnx.helper.make_tensor_value_info(\"output\", onnx.TensorProto.FLOAT, shape=[\"detections\", 16])\n",
"outputs.append(postpro_output)\n",
"gather_node = onnx.helper.make_node(\n",
" \"Gather\",\n",
" inputs=[\"squeezed_output\", \"squeezed_indices\"],\n",
" outputs=[\"output\"],\n",
" name=\"gather_output\",\n",
")\n",
"nodes.append(gather_node)\n",
"\n",
"\n",
"# Make the new graph\n",
"graph = onnx.helper.make_graph(\n",
" nodes,\n",
" graph.name,\n",
" list(graph.input), \n",
" [postpro_output],\n",
" initializer=initializers,\n",
" value_info=graph.value_info,\n",
")\n",
"\n",
"# Create the new model\n",
"onnx_model_prepostpro = onnx.helper.make_model(\n",
" graph,\n",
" opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n",
")\n",
"\n",
"# Save the new model\n",
"onnx.checker.check_model(onnx_model_prepostpro)\n",
"onnx_model_prepostpro_path = onnx_model_export_path[:-5] + \"_prepostpro.onnx\"\n",
"onnx.save(onnx_model_prepostpro, onnx_model_prepostpro_path)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"# image = Image.open(\"../data/people.jpeg\").convert('RGBA')\n",
"# image_onnx = np.array(image)\n",
"\n",
"# ort_session = ort.InferenceSession(\"yolov5s_face_prepostpro.onnx\")\n",
"# test = ort_session.run(None, {\"input\": image_onnx})\n",
"# test[0].shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Optimize model"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"# define path og model and sim model\n",
"onnx_model_sim_path = onnx_model_export_path[:-5] + f\"_opset{onnx_opset}_rgba_sim.onnx\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simplify the model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!onnxsim {onnx_model_prepostpro_path} {onnx_model_sim_path}"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# !onnxsim yolov5s_face_prepostpro.onnx yolov5s_face_opset18_rgba_sim.onnx"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Optimize the graph"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"opt_sess_options = ort.SessionOptions()\n",
"\n",
"opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL\n",
"opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_BASIC\n",
"\n",
"onnx_model_opt_path = onnx_model_export_path[:-5] + f\"_opset{onnx_opset}_rgba_opt.onnx\"\n",
"opt_sess_options.optimized_model_filepath = onnx_model_opt_path\n",
"\n",
"opt_session = ort.InferenceSession(onnx_model_sim_path, opt_sess_options)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Add metadata to model\n",
"\n",
"https://onnx.ai/onnx/intro/python.html#opset-and-metadata"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"new_yolo_face_model = onnx.load(onnx_model_opt_path)\n",
"new_yolo_face_model.producer_name = \"EnteYOLOv5Face\"\n",
"new_yolo_face_model.doc_string = \"YOLOv5 Face detector with built-in pre- and post-processing. Accepts both RGB and RGBA raw bytes input (uint8) in HWC format. Outputs the relevant detections in the format (detections, 16) where the first 4 values are the bounding box coordinates, the fifth is the confidence score, and the rest are the landmarks.\"\n",
"new_yolo_face_model.graph.doc_string = \"\"\n",
"new_yolo_face_model.graph.name = \"SliceRGB+Resize+LetterBox+ToFloat+Unsqueeze+YOLOv5Face+NMS+Slice+Gather\"\n",
"onnx.save(new_yolo_face_model, onnx_model_opt_path)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"!rm {onnx_model_export_path}\n",
"!rm {onnx_model_rgba_path}\n",
"!rm {onnx_model_split_path}\n",
"!rm {onnx_model_nms_path}\n",
"!rm {onnx_model_prepostpro_path}\n",
"!rm {onnx_model_sim_path}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tune some settings"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"# from tqdm import tqdm\n",
"# import time"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"# image = Image.open(\"../data/people.jpeg\").convert('RGBA')\n",
"# image_onnx = np.array(image)\n",
"# time_test_size = 500\n",
"\n",
"# sess_options1 = ort.SessionOptions()\n",
"# sess_options1.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n",
"# # sess_options.enable_profiling = True\n",
"# # sess_options.log_severity_level = 0 # Verbose\n",
"# sess_options1.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n",
"# ort_session1 = ort.InferenceSession(onnx_model_opt_path, sess_options1)\n",
"\n",
"# begin_time_1 = time.time()\n",
"# for i in tqdm(range(time_test_size)):\n",
"# _ = ort_session1.run(None, {\"input\": image_onnx})\n",
"# end_time_1 = time.time()\n",
"# time_1 = end_time_1 - begin_time_1\n",
"\n",
"\n",
"# sess_options2 = ort.SessionOptions()\n",
"# sess_options2.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n",
"# # sess_options.enable_profiling = True\n",
"# # sess_options.log_severity_level = 0 # Verbose\n",
"# sess_options2.inter_op_num_threads = 4\n",
"# # sess_options2.intra_op_num_threads = 4\n",
"# sess_options2.execution_mode = ort.ExecutionMode.ORT_PARALLEL\n",
"# ort_session2 = ort.InferenceSession(onnx_model_opt_path, sess_options2, providers=[\"CPUExecutionProvider\"])\n",
"\n",
"# begin_time_2 = time.time()\n",
"# for i in tqdm(range(time_test_size)):\n",
"# _ = ort_session2.run(None, {\"input\": image_onnx})\n",
"# end_time_2 = time.time()\n",
"# time_2 = end_time_2 - begin_time_2\n",
"\n",
"# print(f\"Time for first execution: {time_1}\")\n",
"# print(f\"Time for second execution: {time_2}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So lessons:\n",
"1. Use sequential execution\n",
"2. Use extended optimizations\n",
"3. Number of inter op doesn't have significant impact\n",
"4. Number of intra op doesn't have significant impact"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One final test:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n",
"imageWidth, imageHeight = image.size\n",
"inputWidth, inputHeight = 640, 640\n",
"print(imageWidth, imageHeight)\n",
"image_onnx = np.array(image)\n",
"\n",
"sess_options1 = ort.SessionOptions()\n",
"sess_options1.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n",
"# sess_options.enable_profiling = True\n",
"# sess_options.log_severity_level = 0 # Verbose\n",
"# sess_options1.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n",
"ort_session = ort.InferenceSession(onnx_model_opt_path)\n",
"raw_detection = ort_session.run(None, {\"input\": image_onnx})[0][0]\n",
"print(raw_detection.shape)\n",
"raw_detection"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [],
"source": [
"from PIL import Image, ImageDraw\n",
"from IPython.display import display\n",
"\n",
"def display_face_detection(image_path, face_box, landmarks):\n",
" # Open the image\n",
" img = Image.open(image_path)\n",
" \n",
" # Create a draw object\n",
" draw = ImageDraw.Draw(img)\n",
" \n",
" # Draw the bounding box\n",
" draw.rectangle(face_box, outline=\"red\", width=2)\n",
" \n",
" # Draw the landmark points\n",
" for point in landmarks:\n",
" x, y = point\n",
" radius = 3\n",
" draw.ellipse([x-radius, y-radius, x+radius, y+radius], fill=\"blue\")\n",
" \n",
" # Display the image\n",
" display(img)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [],
"source": [
"def correct_detection_and_display(image_path, raw_detection, imageWidth, imageHeight, inputWidth, inputHeight):\n",
"\n",
" # Create the raw relative bounding box and landmarks\n",
" box = [0, 0, 0, 0]\n",
" box[0] = (raw_detection[0] - raw_detection[2] / 2) / inputWidth\n",
" box[1] = (raw_detection[1] - raw_detection[3] / 2) / inputHeight\n",
" box[2] = (raw_detection[0] + raw_detection[2] / 2) / inputWidth\n",
" box[3] = (raw_detection[1] + raw_detection[3] / 2) / inputHeight\n",
" landmarks = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]\n",
" i = 0\n",
" for x, y in zip(raw_detection[5:15:2], raw_detection[6:15:2]):\n",
" landmarks[i] = (x / inputWidth, y / inputHeight)\n",
" i += 1\n",
"\n",
" # Correct the bounding box and landmarks for letterboxing during preprocessing\n",
" scale = min(inputWidth / imageWidth, inputHeight / imageHeight)\n",
" scaledWidth = round(imageWidth * scale)\n",
" scaledHeight = round(imageHeight * scale)\n",
" print(f\"scaledWidth: {scaledWidth}, scaledHeight: {scaledHeight}\")\n",
"\n",
" halveDiffX = (inputWidth - scaledWidth) / 2\n",
" halveDiffY = (inputHeight - scaledHeight) / 2\n",
" print(f\"halveDiffX: {halveDiffX}, halveDiffY: {halveDiffY}\")\n",
" scaleX = inputHeight / scaledWidth\n",
" scaleY = inputHeight / scaledHeight\n",
" translateX = - halveDiffX / inputWidth\n",
" translateY = - halveDiffY / inputHeight\n",
" print(f\"scaleX: {scaleX}, scaleY: {scaleY}\")\n",
" print(f\"translateX: {translateX}, translateY: {translateY}\")\n",
"\n",
" box[0] = (box[0] + translateX) * scaleX\n",
" box[1] = (box[1] + translateY) * scaleY\n",
" box[2] = (box[2] + translateX) * scaleX\n",
" box[3] = (box[3] + translateY) * scaleY\n",
"\n",
" for i in range(5):\n",
" landmarks[i] = ((landmarks[i][0] + translateX) * scaleX, (landmarks[i][1] + translateY) * scaleY)\n",
"\n",
" # Convert the bounding box and landmarks to absolute values\n",
" box = [box[0] * imageWidth, box[1] * imageHeight, box[2] * imageWidth, box[3] * imageHeight]\n",
" landmarks = [(x * imageWidth, y * imageHeight) for x, y in landmarks]\n",
"\n",
" print(\"Bounding box:\", box)\n",
" print(\"Landmarks:\", landmarks)\n",
"\n",
" display_face_detection(image_path, box, landmarks)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"image_path = \"../data/man.jpeg\"\n",
"# face_box = (50, 10, 100, 100) # (left, top, right, bottom)\n",
"# landmarks = [\n",
"# (30, 30), # Left eye\n",
"# (80, 30), # Right eye\n",
"# (55, 50), # Nose\n",
"# (35, 80), # Left mouth corner\n",
"# (75, 80) # Right mouth corner\n",
"# ]\n",
"\n",
"correct_detection_and_display(image_path, raw_detection, imageWidth, imageHeight, inputWidth, inputHeight)\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ente_clip",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

BIN
infra/ml/data/man.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
infra/ml/data/people.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
infra/ml/data/singapore.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 KiB

34
infra/ml/pyproject.toml Normal file
View File

@@ -0,0 +1,34 @@
[project]
name = "ente-clean-ml"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"ipykernel>=6.29.5",
"matplotlib>=3.9.2",
"numpy>=2.1.2",
"onnx>=1.17.0",
"onnxconverter-common>=1.14.0",
"onnxruntime-extensions>=0.12.0",
"onnxruntime>=1.19.2",
"onnxsim>=0.4.36",
"opencv-python>=4.10.0.84",
"pandas>=2.2.3",
"pillow>=10.4.0",
"pip>=24.2",
"pyyaml>=6.0.2",
"requests>=2.32.3",
"scipy>=1.14.1",
"seaborn>=0.13.2",
"thop>=0.1.1.post2209072238",
"torch>=2.4.1",
"torchaudio>=2.4.1",
"torchvision>=0.19.1",
"tqdm>=4.66.5",
]
[tool.uv]
dev-dependencies = [
"ipykernel>=6.29.5",
]

1427
infra/ml/uv.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -135,3 +135,44 @@ If needed, Sentry can be stopped by using
cd /home/ente/sentry
sudo docker compose stop
## Backup / Restore
> [!NOTE]
>
> [Upstream docs](https://develop.sentry.dev/self-hosted/backup/#restore)
To backup an existing instance
```sh
sudo ./scripts/backup.sh
```
Then retain the following files
```
sentry/backup.json
sentry/config.yml
.env
```
To restore, run the fresh install. Once it completes, add our custom config
back, ensuring we don't overwrite anything that the new version has
```sh
git diff --no-index ../.env .env
git diff --no-index ../config.yml sentry/config.yml
```
Copy back the backup and run the restore script
```sh
cp ../sentry-backup/backup.json sentry
sudo ./scripts/restore.sh
```
Now start sentry
```sh
sudo docker compose up -d
```

View File

@@ -1,36 +1,36 @@
ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
ente é um aplicativo simples para fazer cópia de segurança e compartilhar suas fotos e vídeos.
Se você está procurando uma alternativa ao Google Fotos com foco em privacidade, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
Se você está procurando por uma alternativa ao Google Fotos focado em privacidade, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los.
Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
Nós temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
ente também torna simples compartilhar seus álbuns com seus entes queridos, mesmo que eles não estejam no ente. Você pode compartilhar links para visualização pública, onde eles podem visualizar seu álbum e colaborar adicionando fotos a ele, mesmo sem uma conta ou app.
ente também torna simples compartilhar seus álbuns com seus entes queridos, mesmo que eles não estejam no ente. Você pode compartilhar links para o público, em que eles podem visualizar seu álbum e colaborar adicionando fotos a ele, mesmo sem uma conta ou aplicativo.
Seus dados criptografados são replicados em 3 locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam.
Seus dados criptografados são replicados em 3 locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam.
Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada!
Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada!
RECURSOS
- Cópia de qualidade original, porque cada pixel é importante
- Planos de família, para que você possa compartilhar o armazenamento com sua família
- Álbuns colaborativos, para que você possa agrupar fotos após uma corrida
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera"
Cópia de resolução original, por cada pixel ser importante
- Planos familiares, para você poder compartilhar o armazenamento com sua família
- Álbuns colaborativos, para você agrupar fotos após uma corrida
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera"
- Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar
- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança
- Suporte humano, porque você vale a pena
- Descrições, para que você possa captar suas memórias e encontrá-las facilmente
- Editor de imagens, para adicionar toques finais
- Favoritar, esconder e reviver suas memórias, pois elas são preciosas
- Importar com um clique do Google, Apple, seu disco rígido e muito mais
- Capacidade de liberar espaço, removendo arquivos salvos com segurança
- Apoio humano, porque você vale a pena
- Descrições, para você poder captar suas memórias e encontrá-las com facilidade
- Editor de imagens, para adicionar últimos toques
- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas
- Importar num só clique do Google, Apple, seu disco rígido e muito mais
- Tema escuro, porque suas fotos parecem bem nele
- 2FA, 3FA, Autenticação biométrica
- e MUITO MAIS!
- e MUITO mais!
PERMISSÕES
ente solicita certas permissões para servir o propósito de um provedor de armazenamento de fotos, que pode ser revisado aqui: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md
ente solicita certas permissões para servir o propósito de um fornecedor de armazenamento de fotos, que pode ser revisado aqui: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md
PREÇO
Não oferecemos planos gratuitos para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com sua família. Você pode encontrar mais informações em ente.io.
Nós não oferecemos planos grátis para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com seus familiares. Você pode encontrar mais informações em ente.io.
SUPORTE
Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas.
AJUDA
Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia.

View File

@@ -1 +1 @@
ente - armazenamento criptografado de fotos
ente - armazenamento de fotos criptografado

View File

@@ -0,0 +1,36 @@
Ente — це простий застосунок для резервного копіювання та обміну фотографіями й відео.
Якщо ви шукали альтернативу Google Фото, яка не шкодить приватності, ви потрапили куди треба. З Ente, вони зберігаються в наскрізному шифруванні. Це означає, що тільки ви в змозі переглядати їх.
У нас є застосунки з відкритим вихідним кодом для Android, iOS, браузера та комп'ютера, і ваші фотографії будуть легко синхронізуватись між усіма вашими пристроями наскрізним шифруванням.
Ente також дозволяє легко ділитися своїми альбомами з близькими, навіть якщо вони не користуються Ente. Ви можете ділитися публічними посиланнями, за якими вони зможуть переглядати ваш альбом і співпрацювати, додаючи до нього фотографії, навіть не маючи облікового запису або застосунку.
Ваші зашифровані дані зберігаються в різних місцях, включаючи бомбосховище в Парижі. Ми серйозно ставимося до спадщини та зробимо все можливе, щоб ваші спогади пережили вас.
Ми тут, щоб зробити найбезпечніший застосунок для фотографій, приєднуйтесь до нашої подорожі!
ФУНКЦІЇ
- Резервні копії оригінальної якості, адже важливий кожен піксель
- Сімейні плани, щоб ви могли ділитися сховищем зі своєю родиною
- Спільні альбоми, щоб ви могли об'єднати фотографії після подорожі
- Спільні теки, на випадок, якщо ви хочете, щоб ваш партнер насолоджувався вашими клацаннями «Камери»
- Посилання на альбоми, які можна захистити паролем і встановити термін дії
- Можливість звільнити місце, видаливши файли, які були надійно збережені в резервній копії
- Служба підтримки з живими людьми, тому що ви того варті
- Описи, щоб ви могли підписувати свої спогади та легко їх знаходити
- Редактор зображень, щоб додати останні штрихи
- Додавайте до обраного; ховайте і переживайте свої спогади, бо вони неоціненні
- Імпорт в один клік з Google, Apple, жорсткого диска тощо
- Темна тема, тому що ваші фотографії в ній мають чудовий вигляд
- 2ЕП, 3ЕП, біометрична авторизація
- і ще БАГАТО чого!
ДОЗВОЛИ
Ente надсилає запити на отримання певних дозволів, що відповідають цілям постачальника послуг зі зберігання фотографій, які можна переглянути тут: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md
ЦІНА
Ми не пропонуємо вічно безплатні тарифи, тому що для нас важливо залишатися стійкими та витримати випробування часом. Натомість ми пропонуємо доступні тарифи, якими ви можете вільно ділитися зі своєю сім'єю. Детальну інформацію можна знайти на ente.io.
ПІДТРИМКА
Ми пишаємося тим, що пропонуємо підтримку живими людьми. Якщо ви наш платний клієнт, ви можете зв'язатися з командою @ente.io й очікувати відповіді від нас протягом 24 годин.

View File

@@ -0,0 +1 @@
Ente — це застосунок для зберігання фотографій з наскрізним шифруванням

View File

@@ -0,0 +1 @@
Ente: зашифроване фотосховище

View File

@@ -0,0 +1 @@
एंटे तस्वीरें

View File

@@ -0,0 +1 @@
nuotraukos,fotografija,šeima,privatumas,debesis,atsarginė kopija,vaizdo įrašai,nuotrauka,šifravimas,saugykla,albumas,alternatyva

View File

@@ -0,0 +1 @@
„Ente“ nuotraukos

View File

@@ -0,0 +1 @@
Užšifruota nuotraukų saugykla

View File

@@ -1,33 +1,33 @@
Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
Ente é um aplicativo simples para copiar com segurança automaticamente e organizar suas fotos e vídeos.
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
Se você esteve procurando por uma alternativa amigável à privacidade para preservar suas memórias, você veio no lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
Temos aplicativos de código aberto em Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
Temos aplicativos de código aberto em Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
Ente também torna simples compartilhar seus álbuns com seus entes queridos. Você pode compartilhá-los diretamente com outros usuários do Ente, criptografados de ponta a ponta; ou com links publicamente visíveis.
Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam.
Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam.
Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada!
Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada!
RECURSOS
- Cópia de qualidade original, porque cada pixel é importante
- Planos de família, para que você possa compartilhar o armazenamento com sua família
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera"
Cópia de resolução original, por cada pixel ser importante
- Planos familiares, para você poder compartilhar o armazenamento com sua família
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera"
- Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar
- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança
- Editor de imagens, para adicionar toques finais
- Favoritar, esconder e reviver suas memórias, pois elas são preciosas
- Importar com um clique de todos os principais provedores de armazenamento
- Capacidade de liberar espaço, removendo arquivos salvos com segurança
- Editor de imagens, para adicionar últimos toques
- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas
- Importar num clique só para todos os fornecedores principais de armazenamento
- Tema escuro, porque suas fotos parecem bem nele
- 2FA, 3FA, Autenticação biométrica
- e MUITO MAIS!
- e MUITO mais!
PREÇO
Não oferecemos planos gratuitos para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com sua família. Você pode encontrar mais informações em ente.io.
Nós não oferecemos planos grátis para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com seus familiares. Você pode encontrar mais informações em ente.io.
SUPORTE
Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas.
AJUDA
Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia.
TERMOS
https://ente.io/terms

View File

@@ -1 +1 @@
fotos,fotografia,família,privacidade,nuvem,backup,vídeos,foto,criptografia,armazenamento,álbum,alternativa
fotos,fotografia,família,privacidade,nuvem,cópiadesegurança,vídeos,foto,criptografia,armazenamento,álbum,alternativa

View File

@@ -0,0 +1,33 @@
Ente — це простий застосунок для автоматичного резервного копіювання та упорядкування ваших фотографій і відео.
Якщо ви шукали альтернативу для збереження своїх спогадів, яка не шкодить приватності, ви потрапили куди треба. З Ente, вони зберігаються в наскрізному шифруванні. Це означає, що тільки ви в змозі переглядати їх.
У нас є застосунки на всіх платформах, і ваші фото будуть легко синхронізуються між усіма вашими пристроями наскрізним шифруванням.
Ente також дозволяє легко ділитися своїми альбомами з близькими. Ви можете або ділитися ними безпосередньо з іншими користувачами Ente через наскрізне шифрування; або із загальнодоступними посиланнями.
Ваші зашифровані дані зберігаються в різних місцях, включаючи бомбосховище в Парижі. Ми серйозно ставимося до спадщини та зробимо все можливе, щоб ваші спогади пережили вас.
Ми тут, щоб зробити найбезпечніший застосунок для фотографій, приєднуйтесь до нашої подорожі!
ФУНКЦІЇ
- Резервні копії оригінальної якості, адже важливий кожен піксель
- Сімейні плани, щоб ви могли ділитися сховищем зі своєю родиною
- Спільні теки, на випадок, якщо ви хочете, щоб ваш партнер насолоджувався вашими клацаннями «Камери»
- Посилання на альбоми, які можна захистити паролем і встановити термін дії
- Можливість звільнити місце, видаливши файли, які були надійно збережені в резервній копії
- Редактор зображень, щоб додати останні штрихи
- Додавайте до обраного; ховайте і переживайте свої спогади, бо вони неоціненні
- Імпорт в один клік з усіх основних постачальників зберігання даних
- Темна тема, тому що ваші фотографії в ній мають чудовий вигляд
- 2ЕП, 3ЕП, біометрична авторизація
- і ще БАГАТО чого!
ЦІНА
Ми не пропонуємо вічно безплатні тарифи, тому що для нас важливо залишатися стійкими та витримати випробування часом. Натомість ми пропонуємо доступні тарифи, якими ви можете вільно ділитися зі своєю сім'єю. Детальну інформацію можна знайти на ente.io.
ПІДТРИМКА
Ми пишаємося тим, що пропонуємо підтримку живими людьми. Якщо ви наш платний клієнт, ви можете зв'язатися з командою @ente.io й очікувати відповіді від нас протягом 24 годин.
УМОВИ
https://ente.io/terms

View File

@@ -0,0 +1 @@
фото,фотографія,сім'я,приватність,хмара,резервне копіювання,відео,фото,шифрування,сховище,альбом,альтернатива

View File

@@ -0,0 +1 @@
Фотографії Ente

View File

@@ -0,0 +1 @@
Зашифроване фотосховище

View File

@@ -0,0 +1 @@
Užšifruota nuotraukų saugykla kurkite atsargines kopijas, tvarkykite ir bendrinkite nuotraukas bei vaizdo įrašus

View File

@@ -0,0 +1 @@
„Ente“ nuotraukos

View File

@@ -1,30 +1,30 @@
Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos.
Ente é um aplicativo simples para copiar com segurança automaticamente e organizar suas fotos e vídeos.
Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
Se você esteve procurando por uma alternativa amigável à privacidade para preservar suas memórias, você veio no lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las.
Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
Nós rmos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee).
Ente também torna simples compartilhar seus álbuns com seus entes queridos. Você pode compartilhá-los diretamente com outros usuários do Ente, criptografados de ponta a ponta; ou com links publicamente visíveis.
Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam.
Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam.
Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada!
Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada!
✨ RECURSOS
- Cópia de qualidade original, porque cada pixel é importante
- Planos de família, para que você possa compartilhar o armazenamento com sua família
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera"
- Cópia de resolução original, por cada pixel é importante
- Planos familiares, para você poder compartilhar o armazenamento com sua família
- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera"
- Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar
- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança
- Editor de imagens, para adicionar toques finais
- Favoritar, esconder e reviver suas memórias, pois elas são preciosas
- Importar com um clique do Google, Apple, seu disco rígido e muito mais
- Capacidade de liberar espaço, removendo arquivos salvos com segurança
- Editor de imagens, para adicionar últimos toques
- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas
- Importar num só clique do Google, Apple, seu disco rígido e muito mais
- Tema escuro, porque suas fotos parecem bem nele
- 2FA, 3FA, Autenticação biométrica
- e MUITO MAIS!
- e MUITO mais!
💲 PREÇO
Não oferecemos planos gratuitos para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com sua família. Você pode encontrar mais informações em ente.io.
Nós não oferecemos planos grátis para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com seus familiares. Você pode encontrar mais informações em ente.io.
🙋 SUPORTE
Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas.
🙋 AJUDA
Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia.

View File

@@ -1 +1 @@
Armazenamento de fotos criptografado - backup, organize e compartilhe suas fotos e vídeos
Armazenamento de fotos criptografado - copie com segurança, organize e compartilhe suas fotos e vídeos

View File

@@ -0,0 +1,30 @@
Ente este o aplicație simplă pentru a face automat copii de rezervă și a vă organiza fotografiile și videoclipurile.
Dacă erați în căutarea unei alternative care să respecte confidențialitatea pentru a vă păstra amintirile, ați ajuns la locul potrivit. Cu Ente, acestea sunt stocate criptate integral (e2ee). Asta înseamnă că numai dvs. le puteți vedea.
Avem aplicații pentru Android, iOS, web și desktop, iar fotografiile dvs. se vor sincroniza perfect între toate dispozitivele dvs. într-un mod criptat integral (e2ee).
De asemenea, Ente simplifică distribuirea albumelor dvs. cu cei dragi. Puteți fie să le distribuiți direct altor utilizatori Ente, criptate integral, fie cu linkuri care pot fi vizualizate public.
Datele dvs. criptate sunt stocate în mai multe locații, inclusiv într-un adăpost antiatomic din Paris. Luăm posteritatea în serios și vă asigurăm că amintirile dvs. vor ajunge la următoarea generație.
Suntem aici pentru a crea cea mai sigură aplicație de fotografii, veniți alături de noi!
✨ CARACTERISTICI
- Copii de rezervă în calitate originală, deoarece fiecare pixel contează
- Planuri de familie, astfel încât să puteți distribui spațiul cu familia dvs.
- Dosare distribuite, în cazul în care doriți ca partenerul dvs. să se bucure și de fotografiile dvs.
- Link-uri pentru albume, care pot fi protejate cu o parolă și setate să expire
- Abilitatea de a elibera spațiu, prin eliminarea fișierelor care au fost salvate în siguranță
- Editor de imagini, pentru a adăuga ultimele retușuri
- Evidențiați, ascundeți și retrăiți-vă amintirile, căci sunt prețioase
- Import cu o singură apăsare din Google, Apple, hard disk și multe altele
- Temă întunecată, deoarece fotografiile dvs. arată cu ea
- 2FA, 3FA, autentificare biometrică
- și MULTE altele!
💲 PREȚURI
Nu oferim planuri gratuite pentru totdeauna, deoarece este important pentru noi să rămânem sustenabili și să trecem testul timpului. În schimb, oferim planuri accesibile pe care le puteți distribui liber familiei dvs. Puteți afla mai multe la ente.io.
🙋 ASISTENȚĂ
Suntem mândri să oferim asistență umană. Dacă sunteți clientul nostru plătit, vă puteți adresa la team@ente.io și așteptați un răspuns din partea echipei noastre în termen de 24 de ore.

View File

@@ -0,0 +1 @@
Stocare criptată de fotografii - salvați, organizați și distribuiți-vă fotografiile și videoclipurile

View File

@@ -0,0 +1 @@
Ente Foto

View File

@@ -0,0 +1,30 @@
Ente — це простий застосунок для автоматичного резервного копіювання та упорядкування ваших фотографій і відео.
Якщо ви шукали альтернативу для збереження своїх спогадів, яка не шкодить приватності, ви потрапили куди треба. З Ente, вони зберігаються в наскрізному шифруванні. Це означає, що тільки ви в змозі переглядати їх.
У нас є застосунки для Android, iOS, браузера та комп'ютера, і ваші фотографії будуть легко синхронізуватись між усіма вашими пристроями наскрізним шифруванням.
Ente також дозволяє легко ділитися своїми альбомами з близькими. Ви можете або ділитися ними безпосередньо з іншими користувачами Ente через наскрізне шифрування; або із загальнодоступними посиланнями.
Ваші зашифровані дані зберігаються в різних місцях, включаючи бомбосховище в Парижі. Ми серйозно ставимося до спадщини та зробимо все можливе, щоб ваші спогади пережили вас.
Ми тут, щоб зробити найбезпечніший застосунок для фотографій, приєднуйтесь до нашої подорожі!
✨ ФУНКЦІЇ
- Резервні копії оригінальної якості, адже важливий кожен піксель
- Сімейні плани, щоб ви могли ділитися сховищем зі своєю родиною
- Спільні теки, на випадок, якщо ви хочете, щоб ваш партнер насолоджувався вашими клацаннями «Камери»
- Посилання на альбоми, які можна захистити паролем і встановити термін дії
- Можливість звільнити місце, видаливши файли, які були надійно збережені в резервній копії
- Редактор зображень, щоб додати останні штрихи
- Додавайте до обраного; ховайте і переживайте свої спогади, бо вони неоціненні
- Імпорт в один клік з Google, Apple, жорсткого диска тощо
- Темна тема, тому що ваші фотографії в ній мають чудовий вигляд
- 2ЕП, 3ЕП, біометрична авторизація
- і ще БАГАТО чого!
💲 ЦІНА
Ми не пропонуємо вічно безплатні тарифи, тому що для нас важливо залишатися стійкими та витримати випробування часом. Натомість ми пропонуємо доступні тарифи, якими ви можете вільно ділитися зі своєю сім'єю. Детальну інформацію можна знайти на ente.io.
🙋 ПІДТРИМКА
Ми пишаємося тим, що пропонуємо підтримку живими людьми. Якщо ви наш платний клієнт, ви можете зв'язатися з командою @ente.io й очікувати відповіді від нас протягом 24 годин.

View File

@@ -0,0 +1 @@
Зашифроване фотосховище: робіть резервні копії, впорядковуйте та діліться своїми фото та відео

View File

@@ -0,0 +1 @@
Фотографії Ente

View File

@@ -51,8 +51,6 @@ PODS:
- GoogleUtilities/Reachability (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- fk_user_agent (2.0.0):
- Flutter
- Flutter (1.0.0)
- flutter_email_sender (0.0.1):
- Flutter
@@ -164,12 +162,12 @@ PODS:
- Flutter
- onnxruntime (0.0.1):
- Flutter
- onnxruntime-objc (= 1.15.1)
- onnxruntime-c (1.15.1)
- onnxruntime-objc (1.15.1):
- onnxruntime-objc/Core (= 1.15.1)
- onnxruntime-objc/Core (1.15.1):
- onnxruntime-c (= 1.15.1)
- onnxruntime-objc (= 1.18.0)
- onnxruntime-c (1.18.0)
- onnxruntime-objc (1.18.0):
- onnxruntime-objc/Core (= 1.18.0)
- onnxruntime-objc/Core (1.18.0):
- onnxruntime-c (= 1.18.0)
- open_mail_app (0.0.1):
- Flutter
- OrderedSet (6.0.3)
@@ -206,7 +204,7 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.3):
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- "sqlite3 (3.46.1+1)":
@@ -228,6 +226,8 @@ PODS:
- sqlite3/perf-threadsafe
- sqlite3/rtree
- Toast (4.1.1)
- ua_client_hints (1.4.0):
- Flutter
- uni_links (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
@@ -253,7 +253,6 @@ DEPENDENCIES:
- file_saver (from `.symlinks/plugins/file_saver/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- fk_user_agent (from `.symlinks/plugins/fk_user_agent/ios`)
- Flutter (from `Flutter`)
- flutter_email_sender (from `.symlinks/plugins/flutter_email_sender/ios`)
- flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`)
@@ -292,8 +291,9 @@ DEPENDENCIES:
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
- ua_client_hints (from `.symlinks/plugins/ua_client_hints/ios`)
- uni_links (from `.symlinks/plugins/uni_links/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
@@ -343,8 +343,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
fk_user_agent:
:path: ".symlinks/plugins/fk_user_agent/ios"
Flutter:
:path: Flutter
flutter_email_sender:
@@ -421,10 +419,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/ios"
ua_client_hints:
:path: ".symlinks/plugins/ua_client_hints/ios"
uni_links:
:path: ".symlinks/plugins/uni_links/ios"
url_launcher_ios:
@@ -454,7 +454,6 @@ SPEC CHECKSUMS:
FirebaseCoreInternal: ac26d09a70c730e497936430af4e60fb0c68ec4e
FirebaseInstallations: 58cf94dabf1e2bb2fa87725a9be5c2249171cda0
FirebaseMessaging: c9ec7b90c399c7a6100297e9d16f8a27fc7f7152
fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_email_sender: 02d7443217d8c41483223627972bfdc09f74276b
flutter_image_compress: 5a5e9aee05b6553048b8df1c3bc456d0afaac433
@@ -486,9 +485,9 @@ SPEC CHECKSUMS:
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
native_video_player: d12af78a1a4a8cf09775a5177d5b392def6fd23c
onnxruntime: e9346181d75b8dea8733bdae512a22c298962e00
onnxruntime-c: ebdcfd8650bcbd10121c125262f99dea681b92a3
onnxruntime-objc: ae7acec7a3d03eaf072d340afed7a35635c1c2a6
onnxruntime: e7c2ae44385191eaad5ae64c935a72debaddc997
onnxruntime-c: a909204639a1f035f575127ac406f781ac797c9c
onnxruntime-objc: b6fab0f1787aa6f7190c2013f03037df4718bd8b
open_mail_app: 794172f6a22cd16319d3ddaf45e945b2f74952b0
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
@@ -505,10 +504,11 @@ SPEC CHECKSUMS:
sentry_flutter: 0eb93e5279eb41e2392212afe1ccd2fecb4f8cbe
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e
ua_client_hints: 46bb5817a868f9e397c0ba7e3f2f5c5d90c35156
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3

View File

@@ -295,7 +295,6 @@
"${BUILT_PRODUCTS_DIR}/dart_ui_isolate/dart_ui_isolate.framework",
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
"${BUILT_PRODUCTS_DIR}/file_saver/file_saver.framework",
"${BUILT_PRODUCTS_DIR}/fk_user_agent/fk_user_agent.framework",
"${BUILT_PRODUCTS_DIR}/flutter_email_sender/flutter_email_sender.framework",
"${BUILT_PRODUCTS_DIR}/flutter_image_compress/flutter_image_compress.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview_ios/flutter_inappwebview_ios.framework",
@@ -333,9 +332,10 @@
"${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework",
"${BUILT_PRODUCTS_DIR}/share_plus/share_plus.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/sqflite_darwin/sqflite_darwin.framework",
"${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework",
"${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework",
"${BUILT_PRODUCTS_DIR}/ua_client_hints/ua_client_hints.framework",
"${BUILT_PRODUCTS_DIR}/uni_links/uni_links.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
"${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework",
@@ -390,7 +390,6 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/dart_ui_isolate.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_saver.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fk_user_agent.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_email_sender.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_image_compress.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview_ios.framework",
@@ -428,9 +427,10 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite_darwin.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ua_client_hints.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uni_links.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework",

View File

@@ -1,12 +1,12 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:fk_user_agent/fk_user_agent.dart';
import 'package:package_info_plus/package_info_plus.dart';
import "package:photos/core/configuration.dart";
import "package:photos/core/event_bus.dart";
import 'package:photos/core/network/ente_interceptor.dart';
import "package:photos/events/endpoint_updated_event.dart";
import "package:ua_client_hints/ua_client_hints.dart";
int kConnectTimeout = 15000;
@@ -14,15 +14,14 @@ class NetworkClient {
late Dio _dio;
late Dio _enteDio;
Future<void> init() async {
await FkUserAgent.init();
final packageInfo = await PackageInfo.fromPlatform();
Future<void> init(PackageInfo packageInfo) async {
final String ua = await userAgent();
final endpoint = Configuration.instance.getHttpEndpoint();
_dio = Dio(
BaseOptions(
connectTimeout: kConnectTimeout,
headers: {
HttpHeaders.userAgentHeader: FkUserAgent.userAgent,
HttpHeaders.userAgentHeader: ua,
'X-Client-Version': packageInfo.version,
'X-Client-Package': packageInfo.packageName,
},
@@ -33,7 +32,7 @@ class NetworkClient {
baseUrl: endpoint,
connectTimeout: kConnectTimeout,
headers: {
HttpHeaders.userAgentHeader: FkUserAgent.userAgent,
HttpHeaders.userAgentHeader: ua,
'X-Client-Version': packageInfo.version,
'X-Client-Package': packageInfo.packageName,
},

View File

@@ -449,7 +449,7 @@ class MLDataDB {
final db = await instance.asyncDB;
final List<Map<String, dynamic>> maps = await db.getAll(
'SELECT $personIdColumn, $faceClustersTable.$clusterIDColumn, $faceIDColumn FROM $clusterPersonTable '
'LEFT JOIN $faceClustersTable ON $clusterPersonTable.$clusterIDColumn = $faceClustersTable.$clusterIDColumn',
'INNER JOIN $faceClustersTable ON $clusterPersonTable.$clusterIDColumn = $faceClustersTable.$clusterIDColumn',
);
final Map<String, Map<String, Set<String>>> result = {};
for (final map in maps) {

View File

@@ -29,3 +29,30 @@ class EnteWatch extends Stopwatch {
stop();
}
}
// TimerLogger helps in quickly including the timeTaken for various operation.
// The timeTaken is logged only if it exceeds the logThreshold. With each call to toString, the timer is reset.
// Usage:
// final TimeLogger tlog = TimeLogger(context: "FaceRecognitionService");
// _logger.info("some operation $tlog");
// _logger.info("another operation $tlog");
class TimeLogger {
final String context;
final int logThreshold;
DateTime _start;
TimeLogger({this.context = "TLog", this.logThreshold = 5})
: _start = DateTime.now();
@override
String toString() {
final int diff = DateTime.now().difference(_start).inMilliseconds;
late String res;
if (diff > logThreshold) {
res = "[$context: $diff ms]";
} else {
res = "[]";
}
_start = DateTime.now();
return res;
}
}

View File

@@ -17,6 +17,7 @@ import 'package:intl/message_lookup_by_library.dart';
import 'package:intl/src/intl_helpers.dart';
import 'messages_ar.dart' as messages_ar;
import 'messages_be.dart' as messages_be;
import 'messages_bg.dart' as messages_bg;
import 'messages_ca.dart' as messages_ca;
import 'messages_cs.dart' as messages_cs;
@@ -36,22 +37,27 @@ import 'messages_it.dart' as messages_it;
import 'messages_ja.dart' as messages_ja;
import 'messages_km.dart' as messages_km;
import 'messages_ko.dart' as messages_ko;
import 'messages_lt.dart' as messages_lt;
import 'messages_nl.dart' as messages_nl;
import 'messages_no.dart' as messages_no;
import 'messages_pl.dart' as messages_pl;
import 'messages_pt.dart' as messages_pt;
import 'messages_ro.dart' as messages_ro;
import 'messages_ru.dart' as messages_ru;
import 'messages_sl.dart' as messages_sl;
import 'messages_sv.dart' as messages_sv;
import 'messages_ta.dart' as messages_ta;
import 'messages_te.dart' as messages_te;
import 'messages_th.dart' as messages_th;
import 'messages_ti.dart' as messages_ti;
import 'messages_tr.dart' as messages_tr;
import 'messages_uk.dart' as messages_uk;
import 'messages_zh.dart' as messages_zh;
typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'ar': () => new SynchronousFuture(null),
'be': () => new SynchronousFuture(null),
'bg': () => new SynchronousFuture(null),
'ca': () => new SynchronousFuture(null),
'cs': () => new SynchronousFuture(null),
@@ -71,17 +77,21 @@ Map<String, LibraryLoader> _deferredLibraries = {
'ja': () => new SynchronousFuture(null),
'km': () => new SynchronousFuture(null),
'ko': () => new SynchronousFuture(null),
'lt': () => new SynchronousFuture(null),
'nl': () => new SynchronousFuture(null),
'no': () => new SynchronousFuture(null),
'pl': () => new SynchronousFuture(null),
'pt': () => new SynchronousFuture(null),
'ro': () => new SynchronousFuture(null),
'ru': () => new SynchronousFuture(null),
'sl': () => new SynchronousFuture(null),
'sv': () => new SynchronousFuture(null),
'ta': () => new SynchronousFuture(null),
'te': () => new SynchronousFuture(null),
'th': () => new SynchronousFuture(null),
'ti': () => new SynchronousFuture(null),
'tr': () => new SynchronousFuture(null),
'uk': () => new SynchronousFuture(null),
'zh': () => new SynchronousFuture(null),
};
@@ -89,6 +99,8 @@ MessageLookupByLibrary? _findExact(String localeName) {
switch (localeName) {
case 'ar':
return messages_ar.messages;
case 'be':
return messages_be.messages;
case 'bg':
return messages_bg.messages;
case 'ca':
@@ -127,6 +139,8 @@ MessageLookupByLibrary? _findExact(String localeName) {
return messages_km.messages;
case 'ko':
return messages_ko.messages;
case 'lt':
return messages_lt.messages;
case 'nl':
return messages_nl.messages;
case 'no':
@@ -135,8 +149,12 @@ MessageLookupByLibrary? _findExact(String localeName) {
return messages_pl.messages;
case 'pt':
return messages_pt.messages;
case 'ro':
return messages_ro.messages;
case 'ru':
return messages_ru.messages;
case 'sl':
return messages_sl.messages;
case 'sv':
return messages_sv.messages;
case 'ta':
@@ -149,6 +167,8 @@ MessageLookupByLibrary? _findExact(String localeName) {
return messages_ti.messages;
case 'tr':
return messages_tr.messages;
case 'uk':
return messages_uk.messages;
case 'zh':
return messages_zh.messages;
default:

View File

@@ -26,6 +26,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("مرحبًا مجددًا!"),
"ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage(
"أُدركُ أنّني فقدتُ كلمة مروري، فقد أفقد بياناتي لأن بياناتي <underline>مشفرة تشفيرًا تامًّا من النهاية إلى النهاية</underline>."),
"add": MessageLookupByLibrary.simpleMessage("Add"),
"addName": MessageLookupByLibrary.simpleMessage("Add name"),
"addNameOrMerge":
MessageLookupByLibrary.simpleMessage("Add name or merge"),
"addNewPerson": MessageLookupByLibrary.simpleMessage("Add new person"),
"cancel": MessageLookupByLibrary.simpleMessage("إلغاء"),
"decrypting": MessageLookupByLibrary.simpleMessage("فك التشفير..."),
"email": MessageLookupByLibrary.simpleMessage("البريد الإلكتروني"),
@@ -33,6 +38,10 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("أدخل عنوان بريدك الإلكتروني"),
"enterYourRecoveryKey":
MessageLookupByLibrary.simpleMessage("أدخل رمز الاسترداد"),
"extraPhotosFound":
MessageLookupByLibrary.simpleMessage("Extra photos found"),
"extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage(
"Extra photos found for \$text"),
"forgotPassword":
MessageLookupByLibrary.simpleMessage("نسيت كلمة المرور"),
"incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage(
@@ -41,10 +50,14 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("مفتاح الاسترداد غير صحيح"),
"invalidEmailAddress": MessageLookupByLibrary.simpleMessage(
"عنوان البريد الإلكتروني غير صالح"),
"mergeWithExisting":
MessageLookupByLibrary.simpleMessage("Merge with existing"),
"newPerson": MessageLookupByLibrary.simpleMessage("New person"),
"noRecoveryKey":
MessageLookupByLibrary.simpleMessage("ما من مفتاح استرداد؟"),
"noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage(
"لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد بسبب طبيعة بروتوكول التشفير الخاص بنا من النهاية إلى النهاية"),
"personName": MessageLookupByLibrary.simpleMessage("Person name"),
"recoverButton": MessageLookupByLibrary.simpleMessage("استرداد"),
"recoverySuccessful":
MessageLookupByLibrary.simpleMessage("نجح الاسترداد!"),

128
mobile/lib/generated/intl/messages_be.dart generated Normal file
View File

@@ -0,0 +1,128 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a be locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'be';
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"accountWelcomeBack":
MessageLookupByLibrary.simpleMessage("З вяртаннем!"),
"activeSessions":
MessageLookupByLibrary.simpleMessage("Актыўныя сеансы"),
"add": MessageLookupByLibrary.simpleMessage("Add"),
"addName": MessageLookupByLibrary.simpleMessage("Add name"),
"addNameOrMerge":
MessageLookupByLibrary.simpleMessage("Add name or merge"),
"addNewPerson": MessageLookupByLibrary.simpleMessage("Add new person"),
"askDeleteReason": MessageLookupByLibrary.simpleMessage(
"Якая асноўная прычына выдалення вашага ўліковага запісу?"),
"cancel": MessageLookupByLibrary.simpleMessage("Скасаваць"),
"confirmAccountDeletion": MessageLookupByLibrary.simpleMessage(
"Пацвердзіць выдаленне ўліковага запісу"),
"confirmDeletePrompt": MessageLookupByLibrary.simpleMessage(
"Так. Я хачу незваротна выдаліць гэты ўліковы запіс і яго даныя ва ўсіх праграмах."),
"confirmPassword":
MessageLookupByLibrary.simpleMessage("Пацвердзіць пароль"),
"createAccount":
MessageLookupByLibrary.simpleMessage("Стварыць уліковы запіс"),
"createNewAccount":
MessageLookupByLibrary.simpleMessage("Стварыць новы ўліковы запіс"),
"decrypting": MessageLookupByLibrary.simpleMessage("Расшыфроўка..."),
"deleteAccount":
MessageLookupByLibrary.simpleMessage("Выдаліць уліковы запіс"),
"deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage(
"Нам шкада, што вы выдаляеце свой уліковы запіс. Абагуліце з намі водгук, каб дапамагчы нам палепшыць сэрвіс."),
"deleteAccountPermanentlyButton": MessageLookupByLibrary.simpleMessage(
"Незваротна выдаліць уліковы запіс"),
"deleteEmailRequest": MessageLookupByLibrary.simpleMessage(
"Адпраўце ліст на <warning>account-deletion@ente.io</warning> з вашага зарэгістраванага адраса электроннай пошты."),
"deleteReason1": MessageLookupByLibrary.simpleMessage(
"У вас адсутнічае важная функцыя, якая мне неабходна"),
"deleteReason2": MessageLookupByLibrary.simpleMessage(
"Праграма або пэўная функцыя не паводзіць сябе так, як павінна"),
"deleteReason3": MessageLookupByLibrary.simpleMessage(
"Я знайшоў больш прывабны сэрвіс"),
"deleteReason4":
MessageLookupByLibrary.simpleMessage("Прычына адсутнічае ў спісе"),
"deleteRequestSLAText": MessageLookupByLibrary.simpleMessage(
"Ваш запыт будзе апрацаваны цягам 72 гадзін."),
"email": MessageLookupByLibrary.simpleMessage("Электронная пошта"),
"entePhotosPerm": MessageLookupByLibrary.simpleMessage(
"Праграме <i>неабходны доступ</i> для захавання вашых фатаграфій"),
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
"Увядзіце сапраўдны адрас электронная пошты."),
"enterYourEmailAddress": MessageLookupByLibrary.simpleMessage(
"Увядзіце свой адрас электроннай пошты"),
"enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage(
"Увядзіце свой ключ аднаўлення"),
"extraPhotosFound":
MessageLookupByLibrary.simpleMessage("Extra photos found"),
"extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage(
"Extra photos found for \$text"),
"feedback": MessageLookupByLibrary.simpleMessage("Водгук"),
"forgotPassword":
MessageLookupByLibrary.simpleMessage("Забыліся пароль"),
"incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage(
"Вы ўвялі памылковы ключ аднаўлення"),
"incorrectRecoveryKeyTitle":
MessageLookupByLibrary.simpleMessage("Няправільны ключ аднаўлення"),
"invalidEmailAddress": MessageLookupByLibrary.simpleMessage(
"Памылковы адрас электроннай пошты"),
"kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage(
"Калі ласка, дапамажыце нам з гэтай інфармацыяй"),
"mergeWithExisting":
MessageLookupByLibrary.simpleMessage("Merge with existing"),
"newPerson": MessageLookupByLibrary.simpleMessage("New person"),
"noRecoveryKey":
MessageLookupByLibrary.simpleMessage("Няма ключа аднаўлення?"),
"noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage(
"Вашы даныя не могуць быць расшыфраваны без пароля або ключа аднаўлення па прычыне архітэктуры наша пратакола скразнога шыфравання"),
"ok": MessageLookupByLibrary.simpleMessage("Добра"),
"oops": MessageLookupByLibrary.simpleMessage("Вой"),
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
"personName": MessageLookupByLibrary.simpleMessage("Person name"),
"recoverButton": MessageLookupByLibrary.simpleMessage("Аднавіць"),
"recoverySuccessful":
MessageLookupByLibrary.simpleMessage("Паспяховае аднаўленне!"),
"selectReason":
MessageLookupByLibrary.simpleMessage("Выберыце прычыну"),
"sendEmail": MessageLookupByLibrary.simpleMessage("Адправіць ліст"),
"somethingWentWrongPleaseTryAgain":
MessageLookupByLibrary.simpleMessage(
"Нешта пайшло не так. Паспрабуйце яшчэ раз"),
"sorry": MessageLookupByLibrary.simpleMessage("Прабачце"),
"terminate": MessageLookupByLibrary.simpleMessage("Перарваць"),
"terminateSession":
MessageLookupByLibrary.simpleMessage("Перарваць сеанс?"),
"thisDevice": MessageLookupByLibrary.simpleMessage("Гэта прылада"),
"thisWillLogYouOutOfTheFollowingDevice":
MessageLookupByLibrary.simpleMessage(
"Гэта дзеянне завяршыць сеанс на наступнай прыладзе:"),
"thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage(
"Гэта дзеянне завяршыць сеанс на вашай прыладзе!"),
"toResetVerifyEmail": MessageLookupByLibrary.simpleMessage(
"Праверце электронную пошту, каб скінуць свой пароль."),
"verify": MessageLookupByLibrary.simpleMessage("Праверыць"),
"verifyEmail":
MessageLookupByLibrary.simpleMessage("Праверыць электронную пошту"),
"yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage(
"Ваш уліковы запіс быў выдалены")
};
}

View File

@@ -21,5 +21,19 @@ class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'bg';
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{};
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"add": MessageLookupByLibrary.simpleMessage("Add"),
"addName": MessageLookupByLibrary.simpleMessage("Add name"),
"addNameOrMerge":
MessageLookupByLibrary.simpleMessage("Add name or merge"),
"addNewPerson": MessageLookupByLibrary.simpleMessage("Add new person"),
"extraPhotosFound":
MessageLookupByLibrary.simpleMessage("Extra photos found"),
"extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage(
"Extra photos found for \$text"),
"mergeWithExisting":
MessageLookupByLibrary.simpleMessage("Merge with existing"),
"newPerson": MessageLookupByLibrary.simpleMessage("New person"),
"personName": MessageLookupByLibrary.simpleMessage("Person name")
};
}

View File

@@ -21,5 +21,19 @@ class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'ca';
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{};
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"add": MessageLookupByLibrary.simpleMessage("Add"),
"addName": MessageLookupByLibrary.simpleMessage("Add name"),
"addNameOrMerge":
MessageLookupByLibrary.simpleMessage("Add name or merge"),
"addNewPerson": MessageLookupByLibrary.simpleMessage("Add new person"),
"extraPhotosFound":
MessageLookupByLibrary.simpleMessage("Extra photos found"),
"extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage(
"Extra photos found for \$text"),
"mergeWithExisting":
MessageLookupByLibrary.simpleMessage("Merge with existing"),
"newPerson": MessageLookupByLibrary.simpleMessage("New person"),
"personName": MessageLookupByLibrary.simpleMessage("Person name")
};
}

Some files were not shown because too many files have changed in this diff Show More