From 0339d7dc2d623e3e962d1d92041e4f130c91be99 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Sun, 24 Feb 2019 16:41:21 +0100 Subject: [PATCH] Version 1.8.0 Added possibility to show a Token as QR-Code Added possibility to hide Tokens by default and reveal on tap Added Base32 input validation for secret Fix progressbar placement for different screen sizes / ambiances Fix About-Page styling for light ambiances --- .gitignore | 1 + harbour-sailotp.pro | 3 +- icons/172x172/harbour-sailotp.png | Bin 0 -> 27731 bytes qml/harbour-sailotp.qml | 1 + qml/pages/About.qml | 10 +- qml/pages/AddOTP.qml | 18 +- qml/pages/MainView.qml | 88 ++++-- qml/pages/QRPage.qml | 34 +-- qml/pages/ScanOTP.qml | 15 +- qml/pages/Settings.qml | 25 +- rpm/harbour-sailotp.changes | 7 + rpm/harbour-sailotp.yaml | 2 +- translations/harbour-sailotp-de.ts | 104 ++++--- translations/harbour-sailotp-es.ts | 101 ++++--- translations/harbour-sailotp-fi.ts | 101 ++++--- translations/harbour-sailotp-fr.ts | 97 ++++--- translations/harbour-sailotp-it.ts | 108 ++++--- translations/harbour-sailotp-pt_BR.ts | 398 ++++++++++++++++++++++++++ translations/harbour-sailotp-ru.ts | 111 ++++--- translations/harbour-sailotp-sv.ts | 105 ++++--- translations/harbour-sailotp-zh_CN.ts | 100 ++++--- translations/harbour-sailotp.ts | 170 ++++++----- 22 files changed, 1122 insertions(+), 477 deletions(-) create mode 100644 icons/172x172/harbour-sailotp.png create mode 100644 translations/harbour-sailotp-pt_BR.ts diff --git a/.gitignore b/.gitignore index dbab0b9..88f42f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # User Specific Project Files *.pro.user *.pro.user.* +*.autosave rpm/harbour-sailotp.spec rpm/harbour-sailotp.spec.* translations/*.qm diff --git a/harbour-sailotp.pro b/harbour-sailotp.pro index 2d418d8..5cb0e0e 100644 --- a/harbour-sailotp.pro +++ b/harbour-sailotp.pro @@ -29,7 +29,7 @@ DISTFILES += qml/harbour-sailotp.qml \ translations/*.ts \ harbour-sailotp.desktop -SAILFISHAPP_ICONS = 86x86 108x108 128x128 +SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 CONFIG += sailfishapp_i18n @@ -38,6 +38,7 @@ TRANSLATIONS = translations/harbour-sailotp-de.ts \ translations/harbour-sailotp-fi.ts \ translations/harbour-sailotp-fr.ts \ translations/harbour-sailotp-it.ts \ + translations/harbour-sailotp-pt_BR.ts \ translations/harbour-sailotp-ru.ts \ translations/harbour-sailotp-sv.ts \ translations/harbour-sailotp-zh_CN.ts diff --git a/icons/172x172/harbour-sailotp.png b/icons/172x172/harbour-sailotp.png new file mode 100644 index 0000000000000000000000000000000000000000..038dd0244cad68f290b3ffc3d2224251a8caa029 GIT binary patch literal 27731 zcmXt9byQT{+a1!OhY*Gk7$k-Ur6q@wlpz$54hiW7DPic8mhSEl0qK&Kl9F!ekdE)Z zzqLNrA^u^_x%WJ=pS|}9Q&W{Ez@@?kfj|TbuVvJM-{t>(gRz01TfFkKz%NW^gn}j* z`0@sug@QozAO#sIO^@_HtqPGe1F6gxb89Uj{h8EX2ZlFP-`0HBn*Q|fud9SB9@L01 zFqnSW^@9r)XDodrJ=#3ib1-`TXL>1r%pH13j0~!sKo=4@49>tq&tk9gAP(~6wK%=_ zrk=JNYY|l1WcTFrmrYM~#{4B^zPEf$OY?bHuxP)3w8!-8*_C*_GQGR*LVq~Vx_=4k z2ryphwM2R9_v7@#ik^j}!^x^mbWljehtu)rwjcSNK$@JRA7!;FlK3j#{;t<$dLVmR zV8$Mvr(S9mxl6U3I+#+ZHuzNWsT|lM;RPtvA5O*q&i#3r_wzFM=UJ}hesIp7?3Y*I z0E7OsRFxT90e$zz&E}Sh6OW<;&lZg3<)@O)>kSQDYDeizGovfl(0R=cpG5 zcu@j7!htiKERdHI($)A>)>Tuhf;xCNIENIBe2U<3P<+L_oe@y##v!|VgPii4I3hxe z1VyeN!9W!LL?Az>4e&#|#h7m;v#)*Fk0ab42ODtQ=C&AN{eH)V!mNa${XF%s3^uY^ zc=#0^6~U)|*CE`3>C!?i3j92QqP-yZ`R9gD>J|Ys!jat)wzjjeG)KSN22M5Q#MWpvNipvsI zIJa;7?mymjSGCK*Fj3u-Fb;*!B(-?}|dCaoJLhysKSLp@b@e~etG=fPbA zYlNdFYCD?-ST`~0(dp?iQ@s1zLorQHF&K|rw%8CdTi-*glKW+yI3AwKAbAM8ztGAa z#Fg5i&2p9ejppu2LhL40z+Xj|3NU0#Lok22c1wXZ8#{&K>WKM>q~&Noa) ziD|)Cjw&kGB$^yCK*!7aZIOOQY4&hXAjw)fH#z&`-!+pFvvMx~JXEY!U`<1AE(dkw zw96=`D(jODkQ#{WBvuu~X8ar^8Ja9fVuH?iouPt|grLWXWhHZOH$rN%RT7Cc@JG=~ zc?;1UKr*OUup|_hm^eC`GT-JV>__(u%V)Y*`JX4hoJYX z*5ii>Zq=@bgI?J`dzUrEd;4$xy1LCfUahbGnx~1fcGWl3sVQGq3a&Aju4jsx@Pw!{ zp%VBNmDmajyP&4=FmH9EyNt*gZl)#81+%IwktFfVqz=!S(ZMX%=Y?1bI;3AEe0(rF zVsd}tb>~paW`He;5mW|HJAVDk>q%d~b*Um}zmG!Rn$!O>&Zey&Rm(OXCEjEOQ!m=N zv`nWKvbOu5M}YPvM0}_oH%6b`S+x>^pdmTxlYD!1ioL=ILgrBuO~zyu@Pteb2jAvg ztNx)<5ql@Qmk2Tlf_L{2XD(d~|IPg<`d@v2w{Tjs!IZClH{V~2$Kx3A;0O2)xi(U- zpLBoQTXO9_uI#*i4nA3PYgxRx-}-QQZN&47@(c{S+J2L{k{stt?2qMds8#k|k1O60 zdYXAe!8sa};h3&bgc~%8*X;X8J>fZSfveo>FjDnUVOAE>YGx}U%Zt@~jhXg>yO7QL zmqS1G(m0hs3=oFnJj)Gvqy+lBFWCXU=+WG7hpQF07N6~YxpljRGg{%&c|KtxUmJnm z$Lk$pU!2{*t?I{(E-X-oM6+)O`Y%mIrFTP{SZQZkXzA6^SNiJH@mR9L){X}1tkXEK zbPyjl+gyw@ZI8lopXZmY&bm``Ka9y4vr)Vr`e@IWFD_S54t*&F&XpK&Ph|a1unuuY zc-QP{>N*GBN)Zxbqqn^1Lzo>E<|~*wM@jek#)xTu*-+=RBI_%=1;wFD70|S2xAuGf zkr?(=w^1`2tvnZ`d3mAw-{Qy;jXz|u&)9pXG_O75oPPfjb-gdYoBOyVULQc z$jQcfi!)vlKR1Dl)auwQ|NUEa=0}Z9X7dk&Sg^_M51YxZBUaR3DkmdftUWU7lcPXb zsL_XvFYDc&hO~+QWC?B`2pC&BFJO^e1nWEt7yo>4y>b*SVN~zzJaY_gRB%K3|e!QZJ zN~@%v4QFW14B7ICBx3U6@s9$j`6p>j-$eBG_AXCbTl}`YolGtDMIxu)43&C~uHA(W zrT`5>NA&ApX%->>ka!P|_(u}Hx?!E`m;IL;!pf~LHh-Xt{j8#fp^$@`efWtrBt`X# z{&53MK0V+5X>7hQPHW&}`DEOveaDpMdTj|L#@gAt5V1g_jJ*j}_BecU5n) z*1lVrO!Eym4!sBuSFidwe_|T!coJ%S*Ia1T?nt&7FmfF*nlb=3X7wlO>HcF35^(YPA!TBXNG;@s?~q zQqIG0w-t1;=SIC(7$&RF!XBJ6@^M~W0a?khdvo-gbMFng>%HRVGgGPp!sjwM>awoC z{!YS}4yGDHFrUS8=PdJEo*8`mdZ{S!Zp)x4J1YT(rp(#_EeP*RIk42N$hX2HgSQ}i z{_xNQBhFc2#4wp3+y=Kx^_W>nirxw{N<|zWdyxswY?>_3#b))xQ4MnItt za=f0qwA8C9AKtGr%AT&Cp^C4;>{-`5g^~Z;n8`M?M|tr~&Ad&3MNIMr4+a?^@_!9R zonp`@^z$N(2ma0daB?;bP5-EHmxhia>0*U7BT6cG->yW?VX6rg_#(CXDXbfe-1)-6 z^uZF(tL}9e_x;?~FduHC2xikKNw&T8wYHO7?qzIqHSSeDpS_IE<@g&(nE=6tz1C%E zmPZu2q@7@;Ojs!nl}ufWDzK|>6HYjevYjQKm!Am7RXVd}bzp}2Lc1auFp(%pFedA9 zxTbKVx`Sd44|dSRMmJ@*jBo~}kH5?e#~#l#*QtY^I17q`tl%fBm=sP8D-0{pxr~=K zZJpP>BGa!hRz7(B_ zdf9mAk?DFbDJ_a0@SDA9lan;bP!*}4)tk){L$!xvy~cB;l?y;b$*b!8?q?4^*$dD0 zwsZ7VXX;7912x^*VPD?#I?PYCZq&&jjL0x|`m;VCdSF-3U2ZZJnxFG$n4As??9azOFTS zXRD=Er5*X~9S-XY#H{8e9m0BZJn;VX&B+)BqwU44=0mr#iP_>t&3F6({y=Cs!A$RO zk4TC_!t%n&<>5fpXT%}$~kB1Cy);1!3<-7qa<@&YIT1K?Ozgnp|nqhl5d#ZUyXs9gM5r_w0eT@Weo4((`L?H6@TxFf# z#|Yc<5`Xn5b+Yh`F3G893s zbCFdWrNXUr8N&GcAl%fdle9H60-uQy{C$cEu^K3dj~<5{D5V0vzem9>5T5#5!g`^z z#VNqs!e5^s|AU(KnAQAXsW8I68DWR{s?$rozVeB$^}dC?^h8^Jhb8f6L{lBEvPLB3&^3XVp%G_$i0f`t;`Z z-hD0l>@C`D7Oh0|!yn0A8tydx!6t*$1me#W#W0B`eZcYS zp*;N}HeHYe-42?&emhGWbK=3%(P}^x1DuO2@l7eNE?cJ?O+uO0)SfHHGqLdNYfsIO z{0WLoz)C5^(b6K#R!v>sRN_QQlF1(X(5;_913N+YzH|p})D<5{U%h%YJGaz#cp;D) zh3%C=C=eoD-)H*6L0@$5@}z#b-zmrc`M0Rl%I>#XaF@X?u|`8UOp~dnFx&~hFia90 zn)vjOed7QC*5yIX9#7H*EG~|3uo8vjk;oll73a~}i!X0*gN7_P_QtG9N1JoitmB1# zVk#^?s=P~%JFT557`13GQv8{eHkzeT^ylOHkt7)3G}^0ux&Oe9!u{6ArkP7rCD5QO z$9Dr9P4g3o2>v^esE=}vM$J*!Sn=eK#F4jjnvlpN--3O}Oy>`doUpCcr(XjRY7*i`NoB}7x=0Ya(!h*tWPwrh=YneF7I6f&~ zO|76pD>xbMr@_B&EgmOpShV8ap`U;Mx{4EMlsZmXbfD)X zs-kp~`(Q{Q<#a=hvJP6%4~Ok*Ln0Yq2n}S{<+AF7%q5!3L`m4lNrN4J7mx-AzDiUm!biC(qE(1Rhtur3}MGLN7drD*GA|{YIY6p8eLf-cForq}w@!I0Y#@5%N+o0fs#{43m zyn;DDKXa`1BNq_JuSIv7iwqYp`Puebs_|W6W$8P-^ej#0FYloASp?V8cIiurCj-W3 zM>zz$cfy`Q5NI$gGfM6%XR)ubg4~WUWOkfyM@dQh)hF`gO1;kMvUiRb`#LnjPMARm zG!PGMOgyY*5hxeC*}z&j$ORTqLx8n>^u`A}5G}YH1}wQeV!1rzsh=oqcg*wFUt|>K zkxUbfKvdIe5O?!+@)K~uEN{i#fa8>ZE`!8WWp(Mx?#F{@_%tLJLKH*0Sc3nt74ens zG#d(z*p2YW&3tQI#?A7v#kqC2=D%xnyF4#+l zM1Wx<=$EgXSi`7_L=}W&iE6vst~~$MTZxr{cnGC!qU65+wpm+vi$^3zRB3CvdgYid z;zw&Sn%R5u&vkfYq>~39)M3eoD4LY2n(1~BLhUt&@g0m1QqJ}4w= za`Odls=&C^XsW;JC^ATWQZvESb@F`HEV10)N&G=@G;8^~Wbxvmmm0hLlWoVtQA>;V zr0Xy%u5jVrW^-P0 z>7u|YDgse_bW{OJbh^;zh-B{dt{^;ZLqquzO$3>2n9PA&3yzU|9sS0i$ixB$)##oBOt`(~-t9RX`T+G!C=5at|o8vi)f5GzY$P+^H)2 z_}IsJ;ONraax0?*=C}HDZgEkvV3^CAT@_A;8YLcwtd%`MNR%-IGcB;QCwh&4;v>ez z5hquidH1iq@Y?UWd&yrWRzo`BJS z_I)b)=da7LZA;Xv%qK{$^{eZ%@27JX-(7Y|qG^QDC;5mm(dG{Xfcg$B;13|VM8}kZ z@6E!_W3$fd1_lz=g>bZoHecX(gSNeo&NdhkV5lh%KE^j&X(Sm?jxLP+D^#C!kAvA@ z0EWfh{sqMtnkZ0iU2A&>f}(@}!2j0kHv(<>gvHr;b%xvE2f2wMWwlf2)emjWq4XKW zbi-7QX>PV~r(Waz6hw&>^U_z4`omj$^!fYKqQ~~!e5R7Kxuf#@L?fIa$^J{n#+mMh z52S)2()c#i7F9s)Fucd5^Sk3sN>0w%6A>MguAA!tiX2sx9D`OMeM($(h{EnibA6$0 zV9!7*ot>Sfq@_uhXexGi#k#1l4A=t+Wv;`+i5H-5BSAihVSk78pkRG5&5uneKwreKV;S^Yzgdta@;~gWb z5dF!XKPT%~YeU>81HBR21_r^UrO=pu%f2#|mX?;C%iDnswlqRKUC)Yyav;Ps*>Vi3 z@_?nuCN=ZVj3jA9`eg)~XWo~DdZ2`+^SU(a@7FKP?z-@}=%>^eM-iuSkM5ME@GIL8 zVRk%+L1B!zs9CG%{*3og!S5#c9KY%Ip1rGn<-yd!Rmx`5r=~^rNoq3boy+}1v(KvVj<#{3gd9#0Pd)8Dt!KA6{q>Fdk8 z`aGkkGU(kLO0KD`MepWWY36cscduz}jrvd*)@kHV4=y|}@sz$Zj>9aoN-fr8OUcTT zuXw8zd|Llj(#fdAH8dAKE@LL_MAf6-KLo`9cY27*AzZ-iy$xOCs|EeDn zFjb=YMKo2{M&Nafo&72P4gucp8LC)zZTY_L`71fe;c!j%?(f-H&9`sZL$xcnz6gxe z5$51-<6H_K{n*0z1ph=utbbl&UyWG9Ym4@Qv5tmteAgw8!qURxNyS?{02sC%v1rm) zW#r$mgVF2fZTWOL&-EzMA)5RI{Q4mz@4bi-BorCS?Zk3m4Y-zYfoLeh8w(pA`_zoI zD7o#B#YMPB5YB84+HK>Y`EVIq1$+3vs)QknnB5zDAoB}GW^uDpa7m2j52!o@vom@X zF7+PCg*ZEvNIRe0i?S{EP26q>0F2Yp(maj<*s$Cd^}f+=^>DGp<9vtM&CLxs zMxpI6zLE8x&6Ur?8Srm>>YMce$P`NNp9e4gE21p>nXTf7y6ea{_OEKPvN==LTGI_e z_M(UXzU>7Qr&mq)EWX`SJ8*z^JgiS^+1!eAI@{5X*XOYitXu0Neb*g)rI>nPponFj zxc93x9UJVTv`@Ub&4vI zOVyud6EYHb`?B}EUJS62NBrWm#kE9$Bjujk*xIfxwSM~UxQ<p*9HTL)S0kC1jN7Z@h<1m_2`WJ zOndtlQgnDa1kYarH^6Pk)%|H-@E6ExOjKV^&wdUCp(=H7u9~g@GnS+7FswnvR&O9ob= zw0Qvd0kF`_o{GZnfeHh|=0QfLOsiDVS2}Htw*mAWK(YJpaqQdg$^Uztt*s9)cJTs0 z3F;|@VF0jQ9nE+pQ%BE7Df8it1g@8g61rSu-xN~?9J+r!4oL^sEx+q}Scr(YYF_St zT(q0SOWGVR`}>zz>ps3T*IReRTdQa)y7A6aXIxVxGXG9Zn6tBIk1v#gPn2lp)w4Sx zn%n|-ae4Vl1b2H+lk>J(i6#l#FH62()(t!~ghiGedjVRC%Gd8F`GCo*-;rdOjVTv` z-gX4Q!4)75ukMfhVwN8tF2DQS3IIb1kar{tfvXOozU?t@%Yx+cc*pDdbe~wQr6kqI z34E`NsHoty0ebaIsJ{$xv^KeQGhv`Jzs=5hjUjGPqQ7e% zIBlKRciDQi24d7e6%Cvp`@1S;-OsBIDLcBGX3Ur3_OTNYnBQ#k)ZmQlIw*(?5(R9R z1&|wV{_TBtJD@uJ(-a8oo*oQ>NfOJ4F=Eny!uYYJe#{rbaksX%)VPw1@*6edJu?L< zWksHy-}s;^BjQSPp|8YsPkOi)D>V)vjqG172{bcms<&^`qE5cQ#0}^~E?f{fRm>%m z+*PRKu&2twVZBVUI-D=uet+0cQLqYovsT;YLi#labFAT6O4~}}89-872(rgWXQr8d zqCc~+!OLH8ojj`+rtNOv80O?Kvb80cR>VpzWfnjOiUcqMw;jDv=*xOZfQ=#Q_dr8U zP3=+B6y{qM0uS#1?L;y~hhb?2A;5QVgarO-bic>R74PBL2$RxaYN1L4={60}k@xoY zJWkJ9Qx_I?{u@lJS3}K>$7|JIMwSdDE9+o94^meZ=9WWnP-y)d{$YOLTl0N3${)GN z*ZX*~(m8A~j8#4YT80(TKLNm+y4;IuWRhqF-)F3bf@(& zS7j%tZR|4z0@1~e@Jv4XzX7RN=<3u%R8{#Fz&+&HOTjK;<*N}t+<2fy&d#J`SrYO^ z3$l=4dJuk}njk)nJ54%kqQmevW2fl0Bh$R){zW^Au@-$Bd)u5vyKYzg6vxLQ#whc* z@7|qU4UpcsY!hbM*{s;LM9B_y4a^>YV#D<+)HlsRfMMAvW-az7|L+B`#4T`UQn}sG z&iPgI)O=g2vBjr-a!wFaoy+KPBnay+hTFghiTth@dasjHt%ppQ6fi9kQbR$M|NfbH zniiK}#hUzfZ$n{9^MMtw?22~oE-Zi4|HYSD;cT&TD+UF934H1O?_36v{ZR1d@O2|& zD;)XcWa9;aE*|ASY8$96t)%xviaH8n5ky0#POcT>mPVqq(xD3b0da+^E;XTL4OCpy z*4pkg+Ua@go>w)~2(n;HPmY=A>uae+8+~phq^Q`c2nY6x*x{&iy`RX>y73j8>F4A+25|n`yMjr-`+dr2 zD=MJf<*0ixl9((qm^Dc5rXxZL{c$&5gRUiRGtx7~Gm{O?&I){w1|-&L5utxXl=UU@ z2v4&h==by;-}X!vF41Ja7RLiwQ#L~y1kfO3)3`rk$S~3R)*W+8Nf44S%(Lcb_6Dl9 zl&tnyV-$(Ldn+8Z(^%7u|?r@`#iB$O$0K_>R zKF{%eYduklojptvRH{}=q2)S?oHoT5QvIBVS7?<1C$|`__~0}v!A{=e9Ch*J>1 zUqT?Qi9vv(`f+m*7dPEGC^lT~r?3SA%Nlcq(dRKMqK+1HQ}S{1NP)fmTjpCMlk7!& z^mBNSMpd3}RW~b{B&*8QYxP{LBY1$}4OT2+5Kt55m|h<%+6Ou{MFNx3_j_?=#nqmi zaF@Og$dlDjhI4Pa_W+$MN+b@eR(^^6IAAgSI}n0CRLcXz&vW_c?3$Jcbzl~j|>uWgp&=Wb;W9EJ)#tKxq{usKtqRNj} zD2`$F!4mX>elkQjB!F2^RUudGoL*eQRrFV&;#iu z7cP0t@OyO$rgaID%+W#vwXekWW-@AReUe%6yL+Nu;prm4HVb{~!!^(P74pr%9Z?MU z>pZW;#=1u>QBM}Rd~F(zr(C7*u!cv*fS6&V3OHwcu_z7@F$Ptpj>c$(RwmG3(vAzS z_-a`s-?U*}v8i`DTLL+a%6pyKgUO^^4qJi{fe*!cMW9=Wii*|Z(zW7Js+Km1ZMpGM zmEBrdD_NKf%g=JlX94kBz7|wQ%sWfuMH$Eto$M%-B*fi85X|!dU$r4zu>p6e79xvW zTV-o~zubrDEN2`_@_!a3r;(kQCtai6Ge1wInkmG4vOB?tp9g-m&YRgsay)0`AJR%| z$Cq~HW$^?UgJ%oL8WNwTi#ucg(Q*48`66?{z#(Q5Vefd+ zdRq}BSKP z0v+?F<5UTBK8LFse)m74^FdiRq;eqgTkR)*8>JTJXmhB(UC?|=Z-&Uyqj)yf&4X_& zJC1q_(zrQcU2eKMfx-|4ni`a4tdSYzRDJOh?+xs5vLD<3{16U0!>mqMCfnp69U#`? zq@aAyt>zU@qRw#IeA%NzB=RUATmgxP&vf(j@PJojiJ{v7_XuzSsfA1tSP~RQlL|{M z)7C1z46&qK{f^b&z6GCn;P*k>ZVzACNccuBR7Uh?K8aRvp&|mg(@ed4=XeSL`etuR z7S(jg9JSZ`3_#PuH<}>j)zV^lFl1e)Zu&WKB6==L6rC%XoTp-NJLHz!1zsV8lap<3 zDCQjh+_-a`bj^BhYTAKjB&&5YdnSqY2TFLYHB?GQ`JR*K+vsO>lfOJntrKwq8aemp z<(_eFg_#2Pv5pU-Vig>whGMp({GQywk~Fr!&=V?cpy(R?^hw)mjR2jO7w%up7%3SNY zjltE$Ux8n_Hs+eqv*XzNNZiPR!T$MykQh^A28qgF?s9$pfFfA_f>>4cdvuTuG-BT#l0DRzSb@{*gqygvq=J&(C^k%bx@ykEdv* zd-CDJxgM(H%535lo9ey$R3+^lt9~S^_%K@TgVxMF{nNP2$3R^IkeXSfNTii>xH?{t zwi-?eHEPxc-I}%U;wUcqCC5vo_CjWULYEquc~{QH;f2H;EqW@kBsM1yANTTb5} zzJo>fs4?N~Pt1uONcU zs1qR^g|SCI!nC^eTR_rtg1#q2X_F%~;n}|i+AwOTKRCsH{d1!4F#j%Ls_CCs7)oq= zeX(jaEKIDNim1xz>M3IXOSOc1oXDI(m0*DwoIC=^hF`8?ID{+}KkiJ3k)o7wV+_KM zEsLs2u1tRXDla{yYU@KFaWZMJ1l7nOlSRAb%hfH;3fz;4NrC4=uOrQId0;XFc-=tX zZR%n@!1rGE`E{TQy1k?m#{}KUr!z7qi2fg0;A6K zMTta@0z$TbuR)9=tCFE+82D5~flf}(_0^W1_^GgzRDio7m3t)Ixw zFTu|B^!Y$?^yh!hg+I0v;tZS?-j*fyq^QK;zo^nXk1cZ{*>GaGW>XqQ#VWKwUf^ud z$U3Yq+QnK=Uac`MEC0fk0@|OfmY7$rrtVo@F$DJu2gC96@PNnTU5&f3{%FUD8j~+I z&&f^k*kA(HGu{p#hD!mBo&6KY(lBvSu{K)s+J4ZgPN65u3`Va}2w7_#|NMiopyKEj zN*EG`Ev1f*qpf4#q?oMl|Fe#8L9qCRXOkKOg^QtmgJw>-Ox=MzT1CWzp|*d~IQ+~-0h+So_EeqH|%QPJfS_W`S> zvA8-Pa=$wFdHj;NA+s;&o@4F}~BYuT=`j*gMau+AoS-bJkg3bgFcX@> z_DxqufW-3ag>VCIE-W>5c}4{M(F~DV=p87CvmF^{Fhbj7K;JMJd+dv~pG*4NHmFAv zUA(4q5bqo14-Fd!3-~|m=BsFLqcE-T%J=_GOsSPtPN;^F#Hzm{4uYZhJUW#`o*JgN ztr|-znWRcd!-kO%4ooCp<6HPX2znZy3JAUCeSc}R$q*^AjDlkL8)(MZmVPDaZyyRf z%<=>flIHzAAAGDRQiyQs?OzUTo18otIXNN<`JQCfQpMW_(1;|ezQk1G@Rt$I9e)iD zB(Bx|UEdT_I!yp-@mA47>)>!Sc*&|y?~lW3eD=NH_-g&tR{ayMnyqOCae0FWm&~hG zSH+xOHtLcGM~yAF7dQVxG6`=H1@eR-ja!y{VGf>g#n&IXtaKH?UyC2t-ekU9`|J^y z?sl4n&Z8`=qg`JvtXhHvx+~6wfPxjQrgL1PF|bW2Qc9?w(T^H_o&4~9yUbzU1*4r) zHLZ>NIi@bYcJ#oO!=VR0xA}e?;oL)i>;_6%wcbpx!e#cl{%f8~o3bb;q>9#&wxWrzRI&P3~gG=qDqy(_1Nr@tt|13rWyQSbZmYctU@pzKxCfn*?$4%p^4%N zX9`ajvtW7NzL8)jNa<@3d_1f=xS?)WHXX3n3_&K;r}YYRjOM5}%R}g+ij-R{PGmq` zV5IG+5|%9MOGLV#*LJkjCu8ly5aTcCSXjSUJATT%k}Sj>Z5c1il*rG|U_x4CNN`vZ z4bx?rrZ{K^^1@N{k*%iY{({10ZPp2UM8XC9*rlaiwH(?>{8-x88HB$@0j2I9cfw!A z#8yF5$O|D4XhQ- z2r>+qi_TFAqAqCU`+)JTl)zDWINiCC=dOy-fu^)^ZU{d#a0EI9N3>5$6)pBz@}=ft zwwvLk`Hbg}H)59YWe%tZ0E{&Sx53I>okds!6fL`twpo?tC3%N3{)W^1RjMW}I_xz> z_AeY9{w;T^SlWt{q$>=i)=MjPwdPo%2^!vyg<%xr4ABTH3<%JqhY zi`$)x4KKb!5KR6Wzw4=7;T29DpCR+cXb!O#^xTi^3iHan@q127U5$NKb*>#|4NA{3 zr!L2%E&~!tHn%T?JknTg!STOabd!QiYEo@n?bmxFD8hn42uTZka}{a* znbl&pdXMG6k_Y9)K%IUA+LTf*P$IE9;B-kOr!0fVS07QK=tG`aU*ceGHDf`7xpp^j$LB|Qn zD6qIU-Kr0zrb8If$j+XMic%4t*ogMU@+PdeR+~*BC`UwEq=&g#6}aqDnE{Zqf?nVMx}5(oA|dQeTSY=_R^}dg8)&w z6sZgErTLbxl1?yvPO!u#A-aE!!MG)r?L+N)kq5S2?gzMN_h4z!7={kVYPY{+zh`EU ztjWO4=-kibv6vu;`})#>Ri9|B^8Newv$L})mQR`&!wAqo5zfQZ*uc{=Z$FXa8m1j< z5x7r72aJkZn$rvoa92%)GA{fl7x{j-LfzAWcwPI%$t^MOt;`pXnS$U z;A0P=9`{8qyCyD?!Y}|=a_O~(zqA<3Rj=rB)yKyUM3HzGTUl?y^Sa{VIr<#|YL^*F zX}X)rY05{n3LH7GqYl8J!E$0D|2!5RpvbCN8qU<+k!#hJaHsXno|bc=$neEKW(ax$ zq!MX8AHJrR2$6=#lr=d5*@?nWW@K;nyfZU)qbHe#ZTasX&^#WuTgX+#eO1%R;X4= znUJc)#NI12G>lH21$^uv)br1PNKl{R9)Sj!IMUl)aFV(7 zyG~DE@TqhIB398PAZ3jb+}y%g5C(R|dR)o8f`TE|4Y>V|aTU=MqJPdr>lbYQqvf|o z(!PJXYw#0e1+&fKyb}k~H;4oaS0vRx(*`{^!RhRfRNY`8`ih{5V+f*5{6gYPBgh`^UFnXA17M_y`Ke zwH_Ry=$CVP6*JOBlV71e-q~^d857Z{-Np6-vqZLX4*Nv3RoeeX(nkCBi-QG^(+!2% z+Fl$fB+`L_FhOsU@3{PspMC1|hI6t1)2$LH{=OC1nPN%bQ^XXs8o%aK0EA&CoNmoQ zT)6I(rQi9qJzR{_zjY>jE)!2-E}mBTkkYs|rZZ`Kb<4<~PVTwrCXJ0Rt%bxj<~u;; zotrE|mT1O3&2(#t@@;?oJ*_i$bL5$sz8C-P=cfnFxJ(SE+gXaJzb=~#l4}2@N?Po)uuF_vvc=CaNVD2rhLi~3A z9iyCgA|iy&23W4nC*S;MWYH|s!j$s=Q1`X`@HP9b3(HY5A>RI1>mH25czsVLLw1&T zy(YY2qxu}=#(j=mr+3X8uTQT|O!Zpa2xb5;$Hj#k;~87&NEhS0N+A5+wu+ zVht-4ER`?Es-YA1VZH-@A?0GD^NQIUz*l>gM7z)akML(!A^Kd@a^ckk$8Lr&9U4@g zm`cjOC6Bm`F3Le7T+*7qJVQ9%#zU`aMvAr9i0Ad1>c3kbkIdwS;@g7rvv$s~bWZt) zt7Q5H4!mIF4P7I&$(rWF<@T7W_6I6MpMOs?MLh#njr`&Go#4*{&?FU7V2^qn z$-LZ`Uq^EE6j~?llf;>;-dw)-<{0Jn4?}ID9MB=7EO&{J{C87?{R$Eus%ew{l@QAt zabQsY&P%gqK$dePB;>P&&t=#Y@Pe-!rh3Hqun zp+W~jSH+rL3jI=2NJ*Zsn*jVBv(~yc=c*1X9FP=F4!RLKDO<-Hb*zh&j={-q;RCd5 z!-&bk(=Es6hT!u6P>ddh-_E5YJ9vdWLa6y$@R;}`4F$J;*Te(~7#4P;Xy@S_`<6aN z0{wLdqp98iXV~c}9<0#BZNNjvvw7-#*pTp%q`1(ESzPCZ=D06+_|dIpeY$GSy zoeQ=XHtL^jj(NuF#JPRAS63G$Lm#2<2m~xPL?PeTZ=uPG+TuP`6hK`JdL!NmyitJ9 z(~|@o0`ZGYhO+GR6&Fme`BeaWQsMJ5Wmf~m+CnsTiHRVVn4-Z)r@D23Ru=U*2K|@d z?+kr{ZZD7W7VX}kcgqrMBGe*0_j;WuEuKC3=h0pzigx~Oi;6XjMizmRA`23Ag$-a> z23&|bW;S(>^;(@V9*`A{{2==b*^wuvjq1Ph73v`vlOE%%ss9!n@vds^Zz8*p+ddT7 z-ZzKkxjCu4@eU&%Au??y9y6D}h#VdqDjH{bN+}-u+V}#D-3}X_fz(!uB*NF(h5GKb zmpI)JAc4sK6E45|-iz2RHU~vT5!5dn^c2g7G3}Kg&?tt?y)`*Z=4#c{62#u>I2Jg` zk9@RLEV;1U0btmHf**a+m($|1^}EcDQ%$MiA|WyuVo!^XHM z9j>Zei&si^*c|*HX$x>^uKF$_&j9#g;_mKl{aQKDjNBvtQ`ovt*v;$Iy#d%Y{o!q4 z^WqN*Ddr|Y>GoxL;K6{_?6~)v^Un`YQi;1`j7)JKk%sLQMb^R6aMB?3O3nYSM41BB z^DP-%ojrE9O!{a$txvgmiIM|N5-tN=bXt-9lGfldi-+lnYu~3pG@Mmo8ODE88l4(OylF3$hNE;f>b5oxD9=Aj-F6#ej_oEZEU+OtnXsoHJ`3xw%d}$+Q z(&k2MXz!6)z@57jtA_CZlx}idcp00vt`l9r;4`r9ez(<^*V@Yj((YAC8{+B5Q9`>? z*Uq%(D#ErB_$NKCjy^yKUxg4%%KV$<)%)&*mCR+>cQa4LF$9cSKxW_&#Kt`pf=XId z|F-6zTD!NLq;0U;^q!xWSo~}sclx$8fZl(vd0=bAX=C=!pPu{MOVVnARFz1LG*(jO zKl)oP&x&xd^eQxu6`CT~zeSZ6s<{1CUB2TN+GWqk5`9A^^W`WgXXuMQduPnvv4SE%58Aw4o zF7Fxt+*vZq+CD&4yXv}7Q^ z^w^B&_>c*F^oxxzZ(fXued!x5`xUtRQHF1|x-HFNmQTpS|021=3JZ2@dYN<-BCSV_ zUyUXSn2I-ncbj$p_nnZ>jSB+9?3|>ec|NAD5bZg&rmn=?w~VWkZPxA0`8xn*I36vD z0Ui@3cBE5?>{mneFdZ}$)0Mf4EzYQFQGD?l5ZL1fZorC%YVZE!N0NQ+8+&b9P0Np; z&PL|2e%eFPHsd0DF(|r%$gORTS87%L1{}0-a<6Yaey$vg!e3O z9PXHsFrlsZAv|mykf7DxY5^kYZw@>lgwt8c9C~<|J9*UcFxJeOmN+d&==d=N@#TG% zj}GUg1<;VHTSQ+b2VZ!@s@HG7KU;VLbb)$<{u4Zkja8Q$S)PygJKF z#aTrW(AxZg5`}ioVOad1J)*3ttxIs(J1~TZj(Ne3EgW4|E2rn2zSTSJT{7Prl_OL7 zPIl98(QAl6R4p4b5RJo zaZ}_bDa-MAZ^YHkdJM8`8ZZeqF7zHA+P&!X(yBu1g9>eHywV+l`|UEKI)D-2YlK=l+y zKDl__1g)p?1Q;wf)WECeNMp86#g1@xKomO0qEjgtOI{2pbC|Jac&EQBc!CIpW7`b5 zrs-{H?j#D^(n5OQZ`GIF?M4%rR4>s+9gi6KFSHRgzU>Z+k?2bV9Fr8{4^Y5W4Dtu? zG|)=&h4`f}D**%jmr`s~I6LkZA3;R3xFgw=>+nY^>(pRtnv&iv8eJM)ml(~cp)7^H zi@i%}^;REAYKf%dJD&Xp{l=PiU9?GW3S$Ps2ZJ*mA38$%*&R$kwEk})D@z`cM^7;R zU_gHFX$yZMrvNGk9U$HH_R6X$j@vaB34Qdc3J|UE*E>vj>4EcBSSL=3WrDXDUJ#lK z?p}oe!|(rmUI5yn^Sy%MsIa2^5n!6pRR=94l^mUT$e|zrX&JE60uqTPikt^zhHM>Z<{3WA(eGwy_MCXXq66|KTz;*bm82 zyP-3;YnP>N?zDp;D~+g|N+DagmH*ya$T+w$5Y%n`RDLY8w_r@XI|z@W+WQ=?sU-_s z%Q!qdOt9@3VpH9dp8Tyf0h;HD6kDF?U~KunlCCl?s{d;)jpWiug9y^y9n#&+A_y$q zARs9v-K{7kAe}C?NH@~B(y`J=H~;&4o|pTA&tAUw-gD;6nVA(`dq)SiLX^{?fFbgR-tS83U|^t7LZBMjtfB71 ze@?1NR%JrReRhDB0wKrw#!gky?jZ7lG6KZRKAz3mE%|Oj6%C_T*6KkdRaWj%CiMhW z=Bn4f*HMHGtd=Uo&)zhYF>7DQiEW_?ZeqQic|ajk(d$lpm*e$1j9+bzGOI~S z%rygizz5E_0QV%Pe-W?;ocWb4o$fyWbc?EF2X~ru*YJv?Fp*7oAS@jU)T*wUi$d38 zNy!9`t7F@}eq71?JRHv2ym5Olx!#^>FGITYt%8CA?fi|+C@WN-$`>4C@uRBdD)?qAub6X!(%gTahy)_d3ySVqT_}>w0 z`I(fHQdjvIR5q$GgNJCIb(Nb>9igOQ7u!v-SgtyS6YiqXRg;s84$6HA`xW<0GVjwsqr)UGA78kOF!f)v z(#;~lZ2j~-HGXmN-#zMvY*Z`n_R_ACBF(C!d91tE0Gt)@a4R%FKd)15v@Wg%j(F5# zkBYgG{6vP+mN~rELBFd#0kPD`tDi_RL|C_suQxr<(6_=`rGZouL<+Z9XCTqM&4lo; z3pyTIwYG?-MyQlBaqHbbSnE-j9=9wpoEJ@=uO!o{ImY`i*6idKC){JNSoZW;f?`5On0G^I{nDlhtx$&2nWlY zOHzXLJ}Qkvi1cbH9J|TN6TuL?7|1pY($zfHOl^i>K(8W_n@eu6iO7(zRBq#MkE$!- z?7++GOBBULPZ~}$@*PVGLi@oOWpdj?EE7k* zGF~U&r|I*7-A&||iNiGQFX43LoVt6(qI;}o`0|8WnKN`OUQr%Prz!Knq+~R~MGeW4!@@pT*_n3;7$63V$?F zFI-VPkv=-+-*+8&rU84b)^alu@sY=Nt2pR80eh~sYcH>({Mz1cIW*X%Xv|n!O2?|RrsKUm0F+f);Z4}vXr61EUuMABo6`P*nr~y`Ud&AzO5}5m>75} z={tr3i=)HMmpIFCF(gN}J%lplK)mN=hwp%}MsJe#t5scPxWpNm(3YG|dd*u$h2vD(0C*SG|)WY5)z@J<4hhMUXn z{sC7$3ru$P46(G}L}i7MzJsQ`B`0{@{nN-zL|hSZx2xY7x7{ zzwc}ag}hSV(}-PZ8l)I0 zj8jA_U`t;i{K|221dR1tRF!%^_pno4^nmA!z`WM}ty@I>w0+~!DJbXzTMKj~+l*7ZB9diw zTyUR&CeO6;O(u^(w?SJVG5H)}Bo><{M^d>SR*>|nc%BsJ#d_1j>5ET6sm3}@v30w! z0B6%{xLD;6nu*o6@Lc*3`1!dY3kyq%S}CBhM#a60jEo!t_3AdsMripeKVy9kQ|5+k z$)*_Tgky9)mG_w26>78mcd_F={8m*X$A zV=lp-hk>(x$I67_r$hTzZ({=YX0G zXd)-_drx&T;aQijQsl9X^GP~1iT?4NRYOaQDSH%SBG@anG{W#y@0mfxmhqwK_Gdxr zjLYwyG)6GZsxDm&%fUH2;^aotzX?5z$s@c0J*=m&qg}INS#R_y0Oou-e(C`(fN4kF z*n?>z%t>!XI6kYn#iUB;V_5~L#k!vt#A+xWlyaYD+w#7Sdr5c&AuO!VX2)Ya@W86g zyBXs`Pe(_9nyqTh3AJVqRS!f1P-l{3xJ{(8d3en{#vSzP(R%y-8!L+Icd6S{vx!$i|>!mUF1h50!i*W%N4xjV zh-=ia#N^G1Mu(h-f69^p=h(=J&oOS4K%rkmAOO+oK?5OV4A)(ZpFaWstZ!UgI6=;$ zMNyUeiR$v$r17r-OYJ&fBL;kP1P9oZ9gZQGwmm)2({@We=8fBLxU+cn+P5NG;CQU$HL57TV2j25Md6?4DN&5iQ zSUTV=D=YKZoqkCf{cBy+1Q1>P4dmzBd5up)M>nvzXp;Sr9dF_lJHu+aT*9`|LB5E4 z-H#t}O2zA@PCYY?_P!5Og1lctJOy-U978Dzgyp|tPKK?p^Yn$8v)O8E?Q5G@U^m2R zq@PKt$0ol;SUpr2i0gbLD)}^TMpW%_fGik7t8yPZjl!N^q;vxu_!YU&|GR4dSOefB z5Sny(d5LdYPkyeaxx8oK^9U54$2duMVr$^7Pucw-@H!uOh}kY_gYmi|w0&-pk__aSI~_)o$@T%ID48c z|w0Y$xI6G9~G8$f9*;=Zwd?gJT1 zn?%}}l3!k3MRFNKJ&3g`n=*qQlQwdUO?LLnw5B>dKaI%3+wI0ahl^7zc{o*_i^av9@)Ym>vmIt z%A#V{%f3&$u+Q0h7ur?h_RTJcdX&koT)HeYM`D{8Z%#3S9nnFpFJS`d=>Z3k7r-(Q z&~Em~b?~z{y){L{fNmD_3Toz*J+Gj}?l%5Eb__6dOA`24Vj=%*jhYrY4$eT z5o)QY)yNO|DhJ}GD&Kk@Ow0L6E4Yx_b`_bD^iF<%XGb$g?Cp*JH;kXqkR10nUq_JVc z5{b1dSi_n=Q~|-ytX2=aEu1J|?Yge2D^3x1mg1#KVoLkRs z0s$7d*@%Onw)3J+dE1ELNyVRuRBVuSq2GL=|7Z&AMMBahB9*vA!Q=7t_&y;i3Dc@( z`lb1RlVLh+2*(+xBvp-cA+sIgmCX?wjv>n`kGXQrB1*{g9SooxzErr6aJ<73CyO52 zmY`-cF;&jpMGF5iZB5g@F5)4%5BkufQ845cwOB1S!DD`SiQpOE0T6_LQ@YN_^Sr|~ zE7|fs>~gS)E9mvazkc8PSLj`3dMXxeVbp|lYfH1FM}N8!>+AWzx-r>RR3>c;ZU$47 zA$z6PZxb-6P=?)oK?<;>{b6RDyq!!_?6#9J8iBm%syK8y2mZEPjW>cml5g$IKcGx& zPb)R8R(MR4>?8-aZniT{Vfx0QxTZYSSyF<$VhaGo>bqcB_51R^>n+!$VHFwZy!-MJ zHd0yk7`P}+tU#^;sskP1hELYSUlrJjWk&ctO0pcU4vvlC(cOhdMS(4K>o$F=K`^Rt zKJstn)4M(k&*n}gDnDd8@kH_g@8CUKe*d@u4kjoaoBZ9t;xo`{EZvc$0k zR#Pp>{~ zqPK4|u~8(e&2fod&V*gcoZzA&@9-I`Er__wK`t$-g*bEK zxuC3~wH9^WfOgc3(iZ)PnSp8CZcC=!sN0Z&l8a+prj0OXuP)>I!<)&(fp*xwn}obz zc+$3<%U%(>)C*Q+Rf?xixRaf4BfUF3ErW&eOp1%!{O*LU?yp~zm6v-09SihVbkH#H zM|84J_DqMQok?>?TKuc$tgXNun6tY( zAwVOUSX#dBv;s<5Jh{qBg+LN`jo&Wtn|J%~7hmy{9wfQ7Emn@tC7tvgi%eT4T~G)) zlDHJ>9ZlUuG|vtf{DR&$&pADKdBDw;MJZnjQ_{R)uKrHPdfH(T1xH1i*x_YujXxw+VdJScIY*#_{@r3&^MZ}6Y3!(5NBsxfZH&! zu;?2YP=dUBeNq;(`;UF7(N}6WRm1b9_^+I{R@Hg`)%=XoylGYyMV-XUYUF3%fX_6H zF8Z+#XoEK$wt2NH##LuBhU~9F8vrF}jD?l@@H{h+ZiGmcutWX}##$9P;1HJMfR`Ce zhjd%%`}}zCFa`koIBF5`4J;MQD)cHBlV0AGNu=lF{kw$Z1GoHvzZXf}z- zyfU3H*PIFNbVtzBFbW%)R|lHS{Cy)%i}n3r<*{Z!3-rT78xZd_dW0vs~8 zDA?BDUxbnwQxd<&)KdA=JFIG`nnR!GbQs~ln6M46zh^h))ML7r+2;mSd2Ab!X6l-D zQ@;X#=j!=Mtfa<0Y+VjBa;&gKzY;PVmya?b(t>YORvpQSTB6_u-~d91On(0lfMUH{ z$GSh+OwP&4k!4BWZQri+GOke1B#5ZQ$oj*7*lG%7p>%~jd~9`J-2k!@{=1zkD|BYn zS*?pqKVxfbnNs10cEm`0G}8g_U-Cdzu00a=ChJF(F8W+n?qmPJ5Dl$;8-xJ0pmR;T zvHxCAcDQ;pyk+$`K_RtDT%a*5E1mz75;3%Y5(OQ>{S#i0%r)ITG#zVKRB}{Lz^qeN#1YGbxdE;a9x8;u9>f z5W2khw+0bb5!pMC>Y&Myw=d;D;W})EwYa+lD9gY)E#MnzY@f`DrH9ep} z&4xb}-gcb7E#jlIP*d}9cc`ntr~>Gpzhgth_{tMe-ZSIJj?`w6tuU$cDs6=~PjB6O z&-sS3Aug-ZTtjbXU5r3e-G>K#8#XDk>r5n{h=-`TUOfw+l!t_4S4E>N%S=D?e}4SX z4&+(|2h$|*%{n!&aT-4}n&agC+qZ@kN5hR#ZWY|K0x+%7UDvI`vdNS$ZPF$>H99bF zo=^_)MtfQgjw_-jPecExvUnOTq~iJNZ8iUaXa7n!L_-mRXl<(IC7wSwX zz+@G7clGZ8m_LIq@hG@0{$g`-7DHnE5nnmq&2~PX%vUz~XHpaVr(<1S1~P(T)&|#S z$#rlU;UH#|1ZW=CyaA4Xx~j!Fg;}_P;VFG~`Xi%g_3!S#Jvv9zNJt`iSb(4!2L_nD`5EZc5AQZFz)UU`dQ`~c zal=m>rwEoQGU5DcR(&Z*VsMB#y(dIKCJ);LQ3v>Bu zAAdI9u-UQX)cW*Tv2=g&zPP^AHgBhEvw+G3;W=&M7CK zI0jN_f0FJ820)!xq=4oe&~3sd`aUAWGcAMw*#VzfOiav+akO655M3Hz z1(0KUIlb`kW>#@tv^lVyVM%YR+%xZ;slqWcJrY$#8Xg1`7=>)MP2Q=D9gjd!G8=JF za=0c$u3YXe%-SCoGL7~h%I(kgyD8!|i}o#$B&-Tvl&8u~7!YmjU}97t#8FK;xk|)s zZN1SUKw2U`U&IX(5J2hml83@*dRh(BNx#%(F-hq2q^*xn(~AzB0BR%6JKhFDSS+*2%jO$A=Mc)NSSW4d2NpB`9C#pU0w3*I}c#1=-z$Pd#faN|kj z76ePuR7)NX^_M95TQX-8TM({`Ez6#$Utky_F9A0E+7t{ zOrWi+JgsI3-vw7gnwaB7zjLM?QoR^DBL}?aAlrm>P9i@S>S|y)<>qb+>~|JwEO9qX zhuN%PI{)eW8E`K|8J`V(>|*In6=&b)_hG)s$YQ$XDkKJ5Sx}T2%yjb?0R(1;RCBs9=Ir z=rdh6+8ngNKx8`ucqPK(6V@xrdbVl2o2f467yjMOaWIoSJD!vQZ8GZ_VY&h=N-sd6JU(7^ zZvr&`e@MUC2sgn*4>aLO<@OxYjg^?vhH*v~;t@BU%u{)FzYkiodYwD~C7L8mwj2P+ zvagny@3cU%e2lRNE#T6xo1C<5M-u9>{^Y;zTi&|5nHp_dx3+5c3$J}+o2D~Lf-!>p zpGQ_h9dW};oybPd&QQ3(@(iCR2f2$dRry5`fIWYu>wSFa{U-f?q*Dh;ENWfSzBr37 ztv0Yq5Wq{gort7uce085I?tgt!WglC`4x-k{>Xn4n&}s})?{Tg0FY>O8&=n&Wv`pe zx9?}l-gcTnTSIHwjx3aBx?rFF`646MCCXHSOm0FW`L<9j9PnJ39BbllBGH0xu8GKz zCg$e7Q&T!?OH{2dsk1513NQ%?2>vst&jE=|?(X#BY_}Ma<)pCZzqo~J+EaEM9YKs zuNIjMOaJBr(K}Pk#^<)z3x|g&fmaCT%WS&_lD9Uh!<2cTmbjBtY@WEf++jHFb2&G= zK7p@E^=OpL&ln@X|M){dSK9PraI}5PUbqH-Tzeck_ntUT!n<(pEqApz;u-}S!&K07 z-p~aRgD|#ZzvX@1Xl@}3%JcO*w0Xuo#22sBJY&!n@lqC;EZ#90&D?i_!btOMyf$&5 z;C0gy@z<5pgxcM1viNH*{U)jJX1b?|Mb9JAia60-X8P^>g00@}n^_b-K(49$funOkP^#^x}fXg#4lJDF|%Mbh6dJk_THk&?8U=)z# zx-wo~SzZD74kIOhG>}T#RG$6q@vr!S6;JRzh4_S2JiFx+ZS4hCMYB`BLYbRugKK zN{<%J_%auA2OZq`j|JhRVIRQPuh7{Q%k6hlKps8F@7g5K{>=MYObObB6I8?NFTRhs zzo*bb#H5FyX>nNV*rI{o8H8c45u`4!1$PhJl(Qqd4J`a?wqW#CHSNuArrSUz`K+n` zXVlJvE%RsAL;fptCjBN&YYpX>AUuI+juUY;TPxmXep;nRT)muh{1i&b&3&Ms$3%xC zU`c1vChdRf?=o)krIOo@8U#c)+zZI1PJAoyw&)WNyGNyLGh5UR$Yhr=)HEkrood>f z-Xe}$XdQ0gzW$b91Any?rtN>kLbN$Sl1uE9auan)+l3)741r= zg+rNN`h>PVX(^X~VCITM{&fKTD)Wci*mA5MqSgkkhJI$0myao#mDT46d7(x9Qn%NY zWDrUi8h;-?e1GguT8h>|w-(E%6cL-RI8KG^XGd~qGD_#kbN)~qb)68YDmbn+H+qj~ z8OKC&gYHX>aI=s6^EU{$V_^jTq>>QmUOPLs!VL`0A(802$6E~ll^Mb_`J$#cxDOM$ zz#s!-QyXdt2f<%@xiZZ#R^k@b2pBCqullXHjfrdzN@~2F^OVk}aS$qnwmaYzyFIfp zw#;^4YPpu;D#O&oykTV#2)lXlsa`sfVhYVClAn_gR(3KaNYO9QOZ%Ho==ONv@RBBf z=JpEE$wafon$>!|m%viu?Yt{6fbX-Sut*uexxOkDp6MCJ)^ahn2o7}F3%N>sfd=7E zaF8u<0hvWtPrn=ux=f6yWrGdUWmNcSn3T~dZ8a8R19yflG0a`P40) zE$gDrz&~n4@rI)qy3N;Hcb2z9Tw**bqs(t6+Yd@pWhh3e0RI)=`T5FYfAO6Kps}7v;+I`3Ox?=BhhBPdeKpdLRWpoTjs{Dx=%&W{ z@x!`od0QNa$hf{nvLG)k2cf|Y-;L&ct8tJ|f((Y~^@R5sC<9)K#_&Z9T9sWzv#oQy zKD3f2!3F%CVh}Ggn*^qUXf3DmpR<$3ncySqyGE2}vMFGB-hpRpsNk*TO;itbfU6?0 z6$Y8xj!jcG`c8)bc#GC7to!5VJI_hq__qsObD}(Dg4IC0E|zWduMNc{g}#0H6E4Kg zgl=`pqwMgt#(C%j8VQn;MEsWr4zHkgQv<;;vfShWGWL{w8!~yX3&Ha?yRo39xsEO{ z(!|k`TM3cEvdA9t?1V1+p$uZsXxS|(a>ajhBbuWv8VILCbHcQ3ZYrDO&ok2GHEND^ z!e`72szF#Zf1gi-3j15O8t(l0NiXXkm^XaA3a<^tETHiaL(5T}bXnVC(;|Lfi+ni6 zXJSjX=H9U;V%;EsNGO)Qwp$8=66Ff(wzDZVvnc);d3PfltCxAEry2XkGFC6%kskhN v+WYMxJ9uSUQ1cTn&eLkB8QX7;2kXJ;2?Vi6sT1%kVIbAlT8cIDkcj^Qb}Kkp literal 0 HcmV?d00001 diff --git a/qml/harbour-sailotp.qml b/qml/harbour-sailotp.qml index 8c627ed..74d2173 100644 --- a/qml/harbour-sailotp.qml +++ b/qml/harbour-sailotp.qml @@ -60,6 +60,7 @@ ApplicationWindow path: "/apps/harbour-sailotp" property bool showQrDefaultAction: false + property bool hideTokens: false } // Add an entry to the list diff --git a/qml/pages/About.qml b/qml/pages/About.qml index 248c9a2..671a25a 100644 --- a/qml/pages/About.qml +++ b/qml/pages/About.qml @@ -73,7 +73,7 @@ Page { horizontalAlignment: TextEdit.Center readOnly: true text: qsTr("A Simple Sailfish OTP Generator\n(RFC 6238/4226 compatible)") - color: "white" + color: Theme.primaryColor } TextArea { id: copyright @@ -82,7 +82,7 @@ Page { horizontalAlignment: TextEdit.Center readOnly: true text: qsTr("Copyright: Stefan Brand\nLicense: BSD (3-clause)") - color: "white" + color: Theme.primaryColor } Button { id: manual @@ -108,7 +108,7 @@ Page { horizontalAlignment: TextEdit.Center readOnly: true text: "\n"+qsTr("SailOTP uses the following third party libs:")+"\n\nhttp://caligatio.github.io/jsSHA/\nhttps://code.google.com/archive/p/crypto-js/\nhttp://sourceforge.net/projects/qzxing/\nhttp://fukuchi.org/works/qrencode/" - color: "white" + color: Theme.primaryColor } TextArea { @@ -119,7 +119,7 @@ Page { horizontalAlignment: TextEdit.Center readOnly: true text: qsTr("Contributors:")+"\n\nRobin Appelman: SteamGuard "+qsTr("Support") - color: "white" + color: Theme.primaryColor } TextArea { @@ -130,7 +130,7 @@ Page { horizontalAlignment: TextEdit.Center readOnly: true text: qsTr("Translators:")+"\n\nChinese: BirdZhang\nFinnish: Johan Heikkilä\nFrench: Romain Tartière\nItalian: Tichy\nRussian: moorchegue\nSpanish: p4moedo\nSwedish: Åke Engelbrektson\nEnglish: Stefan Brand\nGerman: Stefan Brand" - color: "white" + color: Theme.primaryColor } } VerticalScrollDecorator { } diff --git a/qml/pages/AddOTP.qml b/qml/pages/AddOTP.qml index e53e79e..152c266 100644 --- a/qml/pages/AddOTP.qml +++ b/qml/pages/AddOTP.qml @@ -71,7 +71,19 @@ Dialog { if (((paramType == "TOTP" || paramType == "TOTP_STEAM") && (otpLabel.text == "" || otpSecret.text == "")) || (paramType == "HOTP" && (otpLabel.text == "" || otpSecret.text == "" || otpCounter.text <= 0))) { notify.show(qsTr("Can't create QR-Code from incomplete settings!"), 4000); } else { - pageStack.push(Qt.resolvedUrl("QRPage.qml"), {paramLabel: otpLabel.text, paramKey: otpSecret.text, paramType: paramType, paramCounter: otpCounter.text, paramLen: otpLen.text}); + var otpurl = ""; + if (paramType == "TOTP") { + if (otpLabel.text != "" && otpSecret.text != "") + otpurl = "otpauth://totp/"+otpLabel.text+"?secret="+otpSecret.text+"&digits="+otpLen.text; + } else if (paramType == "HOTP") { + if (paramLabel != "" && paramKey != "" && paramCounter > 0) + otpurl = "otpauth://hotp/"+otpLabel.text+"?secret="+otpSecret.text+"&counter="+otpCounter.text+"&digits="+otpLen.text; + } + if (otpurl != "") { + pageStack.push(Qt.resolvedUrl("QRPage.qml"), {paramQrsource: otpurl, paramLabel: otpLabel.text, paramQRId: -1}); + } else { + notify.show(qsTr("Can't create QR-Code from incomplete settings!"), 4000); + } } } } @@ -115,6 +127,8 @@ Dialog { text: paramKey != "" ? paramKey : "" placeholderText: qsTr("Secret OTP Key") focus: true + validator: RegExpValidator { regExp: /^(?:[A-Za-z2-7]{8})*(?:[A-Za-z2-7]{2}={6}|[A-Za-z2-7]{4}={4}|[A-Za-z2-7]{5}={3}|[A-Za-z2-7]{7}=)?$/ } + inputMethodHints: Qt.ImhNoPredictiveText horizontalAlignment: TextInput.AlignLeft EnterKey.enabled: text.length > 15 @@ -168,7 +182,7 @@ Dialog { } // Check if we can Save - canAccept: otpLabel.text.length > 0 && otpSecret.text.length >= 16 && otpLen.text >= 1 && ((paramType == "TOTP" && otpDiff.text != "") || paramType == "TOTP_STEAM" || otpCounter.text.length > 0) ? true : false + canAccept: otpLabel.text.length > 0 && otpSecret.text.length >= 16 && otpSecret.acceptableInput && otpLen.text >= 1 && ((paramType == "TOTP" && otpDiff.text != "") || paramType == "TOTP_STEAM" || otpCounter.text.length > 0) ? true : false // Save if page is Left with Add onDone: { diff --git a/qml/pages/MainView.qml b/qml/pages/MainView.qml index eb6451e..cd29e72 100644 --- a/qml/pages/MainView.qml +++ b/qml/pages/MainView.qml @@ -40,6 +40,7 @@ Page { // This holds the time of the last update of the page as Unix Timestamp (in Milliseconds) property double lastUpdated: 0 + property double seconds_global: 0 // Reload the List of OTPs from storage function refreshOTPList() { @@ -56,30 +57,35 @@ Page { function refreshOTPValues() { // get seconds from current Date var curDate = new Date(); - var seconds_global = curDate.getSeconds() % 30 + seconds_global = curDate.getSeconds() % 30 // Iterate over all List entries for (var i=0; i 2000)) { - var curOTP = OTP.calcOTP(appWin.listModel.get(i).secret, appWin.listModel.get(i).type, appWin.listModel.get(i).len, appWin.listModel.get(i).diff, 0) + if (appWin.listModel.get(i).otp === "------" || seconds == 0 || (curDate.getTime() - lastUpdated > 2000)) { + var curOTP = OTP.calcOTP(appWin.listModel.get(i).secret, appWin.listModel.get(i).type, appWin.listModel.get(i).len, appWin.listModel.get(i).diff, 0); appWin.listModel.setProperty(i, "otp", curOTP); + } else if (appWin.coverType === "HOTP" && (curDate.getTime() - lastUpdated > 2000) && appWin.listModel.get(i).fav === 1) { + // If we are coming back from the CoverPage update OTP value if current favourite is HOTP + appWin.listModel.setProperty(i, "otp", appWin.coverOTP); } - } else if (appWin.coverType == "HOTP" && (curDate.getTime() - lastUpdated > 2000) && appWin.listModel.get(i).fav == 1) { - // If we are coming back from the CoverPage update OTP value if current favourite is HOTP - appWin.listModel.setProperty(i, "otp", appWin.coverOTP); } } - // Update the Progressbar - updateProgress.value = 29 - seconds_global // Set lastUpdate property lastUpdated = curDate.getTime(); } + // Reload OTP List on Return to the Page (to e.g. accomodate changed scd ettings) + onStatusChanged: { + if (status === PageStatus.Activating) { + refreshOTPList(); + } + } + Timer { interval: 500 // Timer only runs when app is acitive and we have entries @@ -98,7 +104,7 @@ Page { } MenuItem { text: qsTr("Settings") - visible: false + visible: true onClicked: pageStack.push(Qt.resolvedUrl("Settings.qml")) } MenuItem { @@ -111,25 +117,11 @@ Page { } } - ProgressBar { - id: updateProgress - width: parent.width - maximumValue: 29 - anchors.top: parent.top - anchors.topMargin: Theme.itemSizeExtraSmall - Theme.paddingSmall - // Only show when there are enries - visible: appWin.listModel.count - } SilicaListView { id: otpList - - header: PageHeader { - title: "SailOTP" - } - anchors.fill: parent model: appWin.listModel width: parent.width @@ -140,6 +132,30 @@ Page { hintText: qsTr("Pull down to add a OTP") } + header: Row { + height: Theme.itemSizeSmall + width: parent.width + ProgressBar { + id: updateProgress + anchors.top: parent.top + // Hack to get the Progress Bar in roughly the same spot on Light and Dark Ambiances + anchors.topMargin: Theme.colorScheme === 0 ? Theme.paddingLarge * 1.1 : Theme.paddingSmall * 0.6 + height: Theme.itemSizeSmall + width: parent.width * 0.65 + maximumValue: 29 + value: 29 - seconds_global + // Only show when there are enries + visible: appWin.listModel.count + } + PageHeader { + id: header + anchors.top: parent.top + height: Theme.itemSizeSmall + width: parent.width * 0.35 + title: "SailOTP" + } + } + delegate: ListItem { id: otpListItem menu: otpContextMenu @@ -163,8 +179,14 @@ Page { } onClicked: { - Clipboard.text = otp - notify.show(qsTr("Token for ") + title + qsTr(" copied to clipboard"), 3000); + if (settings.hideTokens) { + otpValue.visible = !otpValue.visible + } else if (settings.showQrDefaultAction) { + pageStack.push(Qt.resolvedUrl("QRPage.qml"), {paramQrsource: otp, paramLabel: title, paramQRId: index}); + } else { + Clipboard.text = otp + notify.show(qsTr("Token for ") + title + qsTr(" copied to clipboard"), 3000); + } } ListView.onRemove: animateRemoval() @@ -211,6 +233,7 @@ Page { text: model.otp color: Theme.highlightColor font.pixelSize: Theme.fontSizeLarge + visible: !settings.hideTokens anchors.horizontalCenter: parent.horizontalCenter } } @@ -231,6 +254,19 @@ Page { Component { id: otpContextMenu ContextMenu { + MenuItem { + text: qsTr("Copy to Clipboard") + visible: settings.hideTokens || settings.showQrDefaultAction + onClicked: { + Clipboard.text = otp + notify.show(qsTr("Token for ") + title + qsTr(" copied to clipboard"), 3000); + } + } + MenuItem { + text: qsTr("Show Token as QR-Code") + visible: !settings.showQrDefaultAction + onClicked: pageStack.push(Qt.resolvedUrl("QRPage.qml"), {paramQrsource: otp, paramLabel: title, paramQRId: index}); + } MenuItem { text: qsTr("Move up") visible: index > 0 ? true : false; diff --git a/qml/pages/QRPage.qml b/qml/pages/QRPage.qml index fe7ac07..a8ee473 100644 --- a/qml/pages/QRPage.qml +++ b/qml/pages/QRPage.qml @@ -35,11 +35,19 @@ Page { allowedOrientations: Orientation.All - property string paramType: "" + property int paramQRId: -1; property string paramLabel: "" - property string paramKey: "" - property int paramLen: 6 - property int paramCounter: 0 + property string paramQrsource: "" + + Timer { + interval: 1000 + // Timer only runs when app is acitive and we have entries + running: Qt.application.active && appWin.listModel.count && paramQRId >= 0 + repeat: true + onTriggered: { + qrImage.source = "image://qqrencoder/"+appWin.listModel.get(paramQRId).otp; + } + } Label { id: qrLabel @@ -54,24 +62,16 @@ Page { id: qrImage anchors.horizontalCenter: parent.horizontalCenter y: 200 + width: Theme.buttonWidthLarge + height: Theme.buttonWidthLarge cache: false } Component.onCompleted: { - - var otpurl = ""; - if (paramType == "TOTP") { - if (paramLabel != "" && paramKey != "") - otpurl = "otpauth://totp/"+paramLabel+"?secret="+paramKey+"&digits="+paramLen; - - } else if (paramType == "HOTP") { - if (paramLabel != "" && paramKey != "" && paramCounter > 0) - otpurl = "otpauth://hotp/"+paramLabel+"?secret="+paramKey+"&counter="+paramCounter+"&digits="+paramLen; - } - if (otpurl != "") { - qrImage.source = "image://qqrencoder/"+otpurl; + if (paramQrsource !== "") { + qrImage.source = "image://qqrencoder/"+paramQrsource; } else { - notify.show(qsTr("Can't create QR-Code from incomplete settings!"), 4000); + notify.show(qsTr("Can't create QR-Code from an empty String"), 4000); } } } diff --git a/qml/pages/ScanOTP.qml b/qml/pages/ScanOTP.qml index 81b5cc2..fc42aa8 100644 --- a/qml/pages/ScanOTP.qml +++ b/qml/pages/ScanOTP.qml @@ -77,12 +77,7 @@ Page { flash.mode: Camera.FlashOff captureMode: Camera.CaptureStillImage focus.focusMode: Camera.FocusContinuous - - imageCapture { - onImageSaved: { - decoder.decodeImageFromFile(XDG_CACHE_DIR + "/qrscan.jpg"); - } - } + imageCapture.onImageSaved: { decoder.decodeImageFromFile(path); } } QZXing { @@ -92,17 +87,17 @@ Page { var ret = URL.decode(tag); var len = 6 scanning = false - if (ret && ret.type != "" && ret.title != "" && ret.secret != "" && (ret.counter != "" || ret.type == "TOTP")) { - if (ret.digits != "") { + if (ret && ret.type !== "" && ret.title !== "" && ret.secret !== "" && (ret.counter !== "" || ret.type === "TOTP")) { + if (ret.digits !== "") { len = ret.digits } - pageStack.replace(Qt.resolvedUrl("AddOTP.qml"), {parentPage: parentPage, paramLabel: ret.title, paramKey: ret.secret, paramType: ret.type, paramCounter: ret.counter, paramLen: len, paramNew: true}) + pageStack.replace(Qt.resolvedUrl("AddOTP.qml"), {parentPage: parentPage, paramLabel: ret.title, paramKey: ret.secret.toUpperCase(), paramType: ret.type, paramCounter: ret.counter, paramLen: len, paramNew: true}) } else { notify.show(qsTr("No valid Token data found."), 3000); } } - onDecodingFinished: if (succeeded==false && scanning) scanTimer.start(); + onDecodingFinished: { if (succeeded==false && scanning) scanTimer.start(); } } FileIO { diff --git a/qml/pages/Settings.qml b/qml/pages/Settings.qml index 52daeec..9d80362 100644 --- a/qml/pages/Settings.qml +++ b/qml/pages/Settings.qml @@ -51,12 +51,29 @@ Page { SectionHeader { text: qsTr("Behaviour") } TextSwitch { - id: showQrDefault + id: showQrDefaultAction checked: settings.showQrDefaultAction - text: qsTr("Show Token as QRCode on Tap") - onClicked: settings.showQrDefaultAction = !settings.showQrDefaultAction + text: qsTr("Show Token as QR on Tap") + onClicked: { + settings.showQrDefaultAction = !settings.showQrDefaultAction; + if (settings.showQrDefaultAction) { + settings.hideTokens = false; + hideTokens.checked = settings.hideTokens + } + } + } + TextSwitch { + id: hideTokens + checked: settings.hideTokens + text: qsTr("Hide Tokens and Reveal on Tap") + onClicked: { + settings.hideTokens = !settings.hideTokens; + if (settings.hideTokens) { + settings.showQrDefaultAction = false; + showQrDefaultAction.checked = settings.showQrDefaultAction + } + } } - } VerticalScrollDecorator { } } diff --git a/rpm/harbour-sailotp.changes b/rpm/harbour-sailotp.changes index beeaf39..86034dc 100644 --- a/rpm/harbour-sailotp.changes +++ b/rpm/harbour-sailotp.changes @@ -1,3 +1,10 @@ +* Sun Feb 24 2019 Stefan Brand 1.8.0-1 +- Added possibility to show a Token as QR-Code +- Added possibility to hide Tokens by default and reveal on tap +- Added Base32 input validation for secret +- Fix progressbar placement for different screen sizes / ambiances +- Fix About-Page styling for light ambiances + * Sun Jun 17 2018 Stefan Brand 1.7.2-1 - Visual fixes for SFOS 2.2.0.29 diff --git a/rpm/harbour-sailotp.yaml b/rpm/harbour-sailotp.yaml index a8b15c7..e3cfa3d 100644 --- a/rpm/harbour-sailotp.yaml +++ b/rpm/harbour-sailotp.yaml @@ -1,6 +1,6 @@ Name: harbour-sailotp Summary: SailOTP -Version: 1.7.2 +Version: 1.8.0 Release: 1 Group: Security URL: https://github.com/seiichiro0185/sailotp/ diff --git a/translations/harbour-sailotp-de.ts b/translations/harbour-sailotp-de.ts index d6f133c..dce1836 100644 --- a/translations/harbour-sailotp-de.ts +++ b/translations/harbour-sailotp-de.ts @@ -43,86 +43,87 @@ Lizenz: BSD (3-Klausel) Show QR-Code - QR-Code anzeigen + QR-Code Anzeigen + Can't create QR-Code from incomplete settings! Ein QR-Code kann nur mit vollständigen Einstellungen erzeugt werden! - - Save - Speichern - - - + Add Hinzufügen - + + Save + Speichern + + + Type Typ - + Time-based (TOTP) Zeitbasiert (TOTP) - + Counter-based (HOTP) Zählerbasiert (HOTP) - + Steam Guard Steam Guard - + Title Titel - + Title for the OTP Titel für das Token - + Secret (at least 16 characters) Schlüssel (mindestens 16 Zeichen) - + Secret OTP Key Geheimer Schlüssel - + Length Länge - + Length of the Token Länge des Tokens - - + + Time Derivation (Seconds) Zeitabweichung (Sekunden) - + Next Counter Value Nächster Zählerwert - + Next Value of the Counter Nächster Wert für den Zähler @@ -250,67 +251,79 @@ Lizenz: BSD (3-Klausel) MainView - + About Über - + Settings Einstellungen - + Export / Import Export / Import - + Add Token Token hinzufügen - + Nothing here Hier ist nichts - + Pull down to add a OTP - Nach unten ziehen zum hinzufügen + Nach unten ziehen zum Hinzufügen - + Deleting - Lösche + Lösche - + + Token for Token für - + + copied to clipboard - kopiert + in die Zwischenablage kopiert - + + Copy to Clipboard + In die Zwischenablage + + + + Show Token as QR-Code + Als QR-Code Zeigen + + + Move up Nach oben - + Move down Nach unten - + Edit Bearbeiten - + Delete Löschen @@ -319,8 +332,8 @@ Lizenz: BSD (3-Klausel) QRPage - Can't create QR-Code from incomplete settings! - Ein QR-Code kann nur mit vollständigen Einstellungen erzeugt werden! + Can't create QR-Code from an empty String + QR-Code kann nciht aus leerer Eingabe erzeugt werden @@ -346,12 +359,12 @@ Lizenz: BSD (3-Klausel) scanne... - + No valid Token data found. Kein gültiges Token gefunden. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Vorschau antippen um den Scan zu starten / zu stoppen. Nach unten ziehen um manuell hinzu zu fügen. @@ -370,8 +383,13 @@ Lizenz: BSD (3-Klausel) - Show Token as QRCode on Tap - Token bei antippen als QR-Code zeigen + Show Token as QR on Tap + Zeige QR-Code beim Antippen + + + + Hide Tokens and Reveal on Tap + Token erst durch Antippen zeigen diff --git a/translations/harbour-sailotp-es.ts b/translations/harbour-sailotp-es.ts index 65f7db6..706480b 100644 --- a/translations/harbour-sailotp-es.ts +++ b/translations/harbour-sailotp-es.ts @@ -47,82 +47,83 @@ Licencia: BSD (de 3 cláusulas) + Can't create QR-Code from incomplete settings! ¡No se puede crear el código QR a partir de una configuración incompleta! - - Save - Guardar - - - + Add Añadir - + + Save + Guardar + + + Type Tipo - + Time-based (TOTP) Basado en tiempo (TOTP) - + Counter-based (HOTP) Basado en contador (HOTP) - + Steam Guard Steam Guard - + Title Título - + Title for the OTP Nombre para el OTP - + Secret (at least 16 characters) Cadena secreta (al menos 16 caracteres) - + Secret OTP Key Llave secreta OTP - + Length Longitud - + Length of the Token Longitud del token - - + + Time Derivation (Seconds) Derivación de tiempo (segundos) - + Next Counter Value Siguiente Contador - + Next Value of the Counter Siguiente valor del contador @@ -250,67 +251,79 @@ Licencia: BSD (de 3 cláusulas) MainView - + About Acerca de - + Settings Configuración - + Export / Import Exportar/Importar - + Add Token Añadir Token - + Nothing here Nada aquí - + Pull down to add a OTP Tire hacia abajo para añadir tokens OTP - + Deleting Borrando - + + Token for Token para - + + copied to clipboard copiado al portapapeles - + + Copy to Clipboard + Copiar al portapapeles + + + + Show Token as QR-Code + Mostrar código QR + + + Move up Ascender - + Move down Descender - + Edit Editar - + Delete Borrar @@ -319,8 +332,9 @@ Licencia: BSD (de 3 cláusulas) QRPage - Can't create QR-Code from incomplete settings! - ¡No se puede crear el código QR a partir de una configuración incompleta! + Can't create QR-Code from an empty String + Google Translate + No se puede crear un código QR desde una cadena vacía @@ -346,12 +360,12 @@ Licencia: BSD (de 3 cláusulas) Escaneando... - + No valid Token data found. No se han encontrado datos válidos - + Tap the picture to start / stop scanning. Pull down to add Token manually. Toque la imagen para comenzar/parar el escaneo. Tire hacia abajo para una configuración manual. @@ -366,12 +380,19 @@ Licencia: BSD (de 3 cláusulas) Behaviour - + Comportamiento - Show Token as QRCode on Tap - Mostrar el token como código QR al tocar + Show Token as QR on Tap + Google Translate + Mostrar token como QR en el tap + + + + Hide Tokens and Reveal on Tap + Google Translate + Ocultar tokens y revelar en tap diff --git a/translations/harbour-sailotp-fi.ts b/translations/harbour-sailotp-fi.ts index c4f09a1..6115dea 100644 --- a/translations/harbour-sailotp-fi.ts +++ b/translations/harbour-sailotp-fi.ts @@ -47,82 +47,83 @@ Lisenssi: BSD (3-clause) + Can't create QR-Code from incomplete settings! QR-koodin luonti epäonnistui puutteellisten asetuksien takia! - - Save - Tallenna - - - + Add Lisää - + + Save + Tallenna + + + Type Tyyppi - + Time-based (TOTP) Aikapohjainen (TOTP) - + Counter-based (HOTP) Laskentapohjainen (HOTP) - + Steam Guard Steam Guard - + Title Nimi - + Title for the OTP OTP:n nimi - + Secret (at least 16 characters) Salaisuus (vähintään 16 merkkiä) - + Secret OTP Key Salainen OTP-avain - + Length Pituus - + Length of the Token Tunnuksen pituus - - + + Time Derivation (Seconds) Aikapoikkeama (sekunneissa) - + Next Counter Value Seuraava laskenta-arvo - + Next Value of the Counter Laskurin seuraava arvo @@ -251,68 +252,79 @@ Lisenssi: BSD (3-clause) MainView - + About Tietoja - + Settings - Translated using Google Translate Asetukset - + Export / Import Eksportoi / Importoi - + Add Token Lisää tunnus - + Nothing here Tyhjä - + Pull down to add a OTP Vedä alaspäin lisääksesi OTP:n - + Deleting Poistaa - + + Token for Tunnus - + + copied to clipboard kopioitu leikepöydälle - + + Copy to Clipboard + Kopioi leikepöydälle + + + + Show Token as QR-Code + Näytä QR-koodi + + + Move up Siirrä ylös - + Move down Siirrä alas - + Edit Muokkaa - + Delete Poista @@ -321,8 +333,8 @@ Lisenssi: BSD (3-clause) QRPage - Can't create QR-Code from incomplete settings! - QR-koodin luonti ei onnistu puutteellisten asetusten takia! + Can't create QR-Code from an empty String + QR-koodia ei voi luoda tyhjällä merkkijonolla @@ -348,12 +360,12 @@ Lisenssi: BSD (3-clause) Skannataan... - + No valid Token data found. Voimassa olevaa tunnustietoa ei löytynyt. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Käynnistä / lopeta skannaus painamalla kuvaa. Vedä alaspäin lisääksesi tunnuksen käsin. @@ -368,14 +380,19 @@ Lisenssi: BSD (3-clause) Behaviour - Translated using Google Translate Käytös - Show Token as QRCode on Tap - Translated using Google Translate - Kosketa tokenä QR-koodina + Show Token as QR on Tap + Google Translate + Näytä tunnus QR-muodossa Napauta + + + + Hide Tokens and Reveal on Tap + Google Translate + Piilota tokenit ja paljastaa koskettamalla diff --git a/translations/harbour-sailotp-fr.ts b/translations/harbour-sailotp-fr.ts index 8471527..0d279ab 100644 --- a/translations/harbour-sailotp-fr.ts +++ b/translations/harbour-sailotp-fr.ts @@ -46,82 +46,83 @@ Licence : BSD (3 clauses) + Can't create QR-Code from incomplete settings! Impossible de créer un code QR avec des paramètres incomplets ! - + Add Ajouter - + Save Enregistrer - + Type Type - + Time-based (TOTP) Basé sur le temps (TOTP) - + Counter-based (HOTP) Basé sur un compteur (HOTP) - + Steam Guard Steam Guard - + Title Titre - + Title for the OTP - Titre de l'OTP + Titre de l&apos;OTP - + Secret (at least 16 characters) Secret (au moins 16 caractètres) - + Secret OTP Key Clé secrète OTP - + Length Longueur - + Length of the Token Longueur du jeton - - + + Time Derivation (Seconds) Dérivation de temps (secondes) - + Next Counter Value Prochaine valeur du compteur - + Next Value of the Counter Prochaine valeur du compteur @@ -250,68 +251,79 @@ Licence : BSD (3 clauses) MainView - + About À propos - + Settings - Translated using Google Translate Paramètres - + Export / Import Exporter / Importer - + Add Token Ajouter un OTP - + Nothing here Aucun mot de passe - + Pull down to add a OTP Glissez vers le bas pour ajouter un OTP - + Deleting Suppression - + + Token for OTP pour - + + copied to clipboard copié dans le presse-papier - + + Copy to Clipboard + Copier dans le presse-papier + + + + Show Token as QR-Code + Afficher le code QR + + + Move up Déplacer vers le haut - + Move down Déplacer vers le bas - + Edit Modifier - + Delete Supprimer @@ -320,8 +332,9 @@ Licence : BSD (3 clauses) QRPage - Can't create QR-Code from incomplete settings! - Impossible de créer un code QR avec des paramètres incomplets ! + Can't create QR-Code from an empty String + Google Translate + Impossible de créer un code QR à partir d'une chaîne vide @@ -347,12 +360,12 @@ Licence : BSD (3 clauses) Balayer un code - + No valid Token data found. Pas d'information valide trouvée. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Appuyez sur l'image pour démarrer / arréter le balayage. Glissez vers le bas pour entrer les paramètres manuellement. @@ -367,14 +380,20 @@ Licence : BSD (3 clauses) Behaviour - Translated using Google Translate + Google Translate Comportement - Show Token as QRCode on Tap - Translated using Google Translate - Touchez le jeton comme un code QR + Show Token as QR on Tap + Google Translate + Afficher le jeton sous forme de QR au toucher + + + + Hide Tokens and Reveal on Tap + Google Translate + Masquer les jetons et révéler au robinet diff --git a/translations/harbour-sailotp-it.ts b/translations/harbour-sailotp-it.ts index 7c78bcc..ad3d74e 100644 --- a/translations/harbour-sailotp-it.ts +++ b/translations/harbour-sailotp-it.ts @@ -47,82 +47,83 @@ Licenza: BSD (3-clause) + Can't create QR-Code from incomplete settings! Impossibile creare il codice QR da impostizioni incomplete! - - Save - Salva - - - + Add Aggiungi - + + Save + Salva + + + Type Tipo - + Time-based (TOTP) Basato sul tempo (TOTP) - + Counter-based (HOTP) Basato su contatore (HOTP) - + Steam Guard Steam Guard - + Title Titolo - + Title for the OTP Titolo per la OTP - + Secret (at least 16 characters) - Segreto (almeno 16 caratteri) + Segreto (almeno 16 caratteri - + Secret OTP Key Chiave OTP segreta - + Length Lunghezza - + Length of the Token Lunghezza del Token - - + + Time Derivation (Seconds) Derivazione Temporale (Secondi) - + Next Counter Value Valore Prossimo Contatore - + Next Value of the Counter Prossimo Valore del Contatore @@ -250,67 +251,79 @@ Licenza: BSD (3-clause) MainView - + About Informazioni - + Settings Imopstazioni - + Export / Import Esporta / Importa - + Add Token Aggiungi Token - + Nothing here - Qua non c'è nulla + Qua non c&apos;è nulla - + Pull down to add a OTP Trascina giù per aggiungere una OTP - + Deleting Cancellazione - + + Token for Token per - + + copied to clipboard copiato negli appunti - - Move up - Sposta su + + Copy to Clipboard + Copia negli appunti - + + Show Token as QR-Code + Mostra Codice QR + + + + Move up + >Sposta su + + + Move down Sposta giù - + Edit Modifica - + Delete Cancella @@ -319,8 +332,9 @@ Licenza: BSD (3-clause) QRPage - Can't create QR-Code from incomplete settings! - Impossibile creare il codice QR da impostizioni incomplete! + Can't create QR-Code from an empty String + Google Translate + Impossibile creare il codice QR da una stringa vuota @@ -346,12 +360,12 @@ Licenza: BSD (3-clause) Scansione... - + No valid Token data found. Non sono stati trovati dati di Token validi. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Tocca l'immagine per iniziare / fermare la scansione. Trascina giù per aggiungere manualmente un Token. @@ -366,12 +380,20 @@ Licenza: BSD (3-clause) Behaviour + Google Translate Comportamento - Show Token as QRCode on Tap - Mostra il Token come Codice QR al Tocco + Show Token as QR on Tap + Google Translate + Mostra Token come QR alla pressione + + + + Hide Tokens and Reveal on Tap + Google Translate + Nascondi token e rivela alla spina diff --git a/translations/harbour-sailotp-pt_BR.ts b/translations/harbour-sailotp-pt_BR.ts new file mode 100644 index 0000000..a264b83 --- /dev/null +++ b/translations/harbour-sailotp-pt_BR.ts @@ -0,0 +1,398 @@ + + + + + About + + + A Simple Sailfish OTP Generator +(RFC 6238/4226 compatible) + Um Simples Gerador de OTP para Sailfish + + + + Copyright: Stefan Brand +License: BSD (3-clause) + Copyright: Stefan Brand +Licença: BSD (3-clause) + + + + SailOTP uses the following third party libs: + SailOTP usa as seguintes bibliotecas de terceiros + + + + Contributors: + Contribuiram: + + + + Support + Suporte + + + + Translators: + Tradutores: + + + + AddOTP + + + Show QR-Code + Mostrar código QR + + + + + Can't create QR-Code from incomplete settings! + Não foi possível criar Código QR porque a configuração está incompleta! + + + + Add + Adicionar + + + + Save + Salvar + + + + Type + Tipo + + + + Time-based (TOTP) + Baseado em tempo (TOTP) + + + + Counter-based (HOTP) + Baseado em contador (HOTP) + + + + Steam Guard + Steam Guard + + + + Title + Título + + + + Title for the OTP + Título para o OTP + + + + Secret (at least 16 characters) + Segredo (mínimo de 16 caracteres) + + + + Secret OTP Key + Chave secreta OTP + + + + Length + Tamanho + + + + Length of the Token + Tamanho to Token + + + + + Time Derivation (Seconds) + Derivação do tempo (segundos) + + + + Next Counter Value + Próximo valor do contador + + + + Next Value of the Counter + Próximo valor do contador + + + + ExportPage + + + File already exists, choose "Overwrite existing" to overwrite it. + Arquivo já existe, habilite "Sobrescrever existente" para sobrescrevê-lo. + + + + Given file does not exist! + Não foi possíve encontrar o arquivo! + + + + + Export + Exportar + + + + + Import + Importar + + + + Filename + Nome do arquivo + + + + File to import + Arquivo para importar + + + + File to export + Arquivo para exportar + + + + Overwrite existing + Sobrescrever existente + + + + Password + Senha + + + + Password for the file + Senha para o arquivo + + + + Passwords don't match! + Senhas não coincidem! + + + + Passwords match! + Senha correta + + + + Repeated Password for the file + Repetir a senha para o arquivo + + + + Here you can Import Tokens from a file. Put in the file location and the password you used on export. Pull left to start the import. + Importe Tokens salvos em um arquivo. Insira a localização do arquivo e a senha usada durante a exportação. Puxe para a esquerda para iniciar a importação. + + + + Here you can export Tokens to a file. The exported file will be encrypted with AES-256-CBC and Base64 encoded. Choose a strong password, the file will contain the secrets used to generate the Tokens for your accounts. Pull left to start the export. + Exporte os Tokens para um arquivo. O arquivo expotado será criptografado com AES-256-CBC e codificado em Base64. Escolha uma senha forte pois o arquivo conterá todos os segredos usados para gerar os Tokens disponíveis. Puxe para a esquerda para iniciar o processo. + + + + To view the content of the export file outside of SailOTP use the following openssl command: + Para visualizar o conteúdo do arquivo expotado fora do SailOTP use o seguinte comando openssl: + + + + Error writing to file + Não foi possível escrever no arquivo + + + + Token Database exported to + Base de dados dos Tokens exportada para + + + + Could not encrypt tokens. Error: + Não foi possível criptografar Tokens. Erro: + + + + Could not read tokens from Database + Não foi possível ler Tokens da base de dados + + + + Tokens imported from + Tokens importados de + + + + Unable to decrypt file, did you use the right password? + Não foi possível decriptografar arquivo, por favor cheque a senha. + + + + Could not read from file + Não foi possível ler arquivo + + + + MainView + + + About + Sobre + + + + Settings + Configurações + + + + Export / Import + Exportar e importar + + + + Add Token + Adicionar Token + + + + Nothing here + Nada aqui + + + + Pull down to add a OTP + Puxe para baixo para adicionar um OTP + + + + Deleting + Apagando + + + + + Token for + Token para + + + + + copied to clipboard + copiado para a área de transferência + + + + Copy to Clipboard + Copiar para área de transferência + + + + Show Token as QR-Code + Mostrar código QR + + + + Move up + Mover para cima + + + + Move down + Mover para baixo + + + + Edit + Editar + + + + Delete + Apagar + + + + QRPage + + + Can't create QR-Code from an empty String + Google Translate + Não é possível criar QR-Code de uma string vazia + + + + ScanOTP + + + Can't access temporary directory + Não foi possível acessar pasta temporária + + + + Add manually + Adicionar manualmente + + + + Scan Code + Escanear Código + + + + Scanning... + Escaneando... + + + + No valid Token data found. + Não foi possível encontrar Token válido + + + + Tap the picture to start / stop scanning. Pull down to add Token manually. + Toque na imagem para iniciar ou parar o escaneador. Puxe para baixo para adicionar Token manualmente. + + + + Settings + + + Settings + Configurações + + + + Behaviour + Google Translate + Comportamento + + + + Show Token as QR on Tap + Google Translate + Mostrar token como QR na torneira + + + + Hide Tokens and Reveal on Tap + Google Translate + Esconda tokens e revele na torneira + + + diff --git a/translations/harbour-sailotp-ru.ts b/translations/harbour-sailotp-ru.ts index e926443..b643fe9 100644 --- a/translations/harbour-sailotp-ru.ts +++ b/translations/harbour-sailotp-ru.ts @@ -47,82 +47,83 @@ License: BSD (3-clause) + Can't create QR-Code from incomplete settings! Невозможно создать QR-код из-за неполных настроек! - - Save - Сохранить - - - + Add Добавить - + + Save + Сохранить + + + Type Тип - + Time-based (TOTP) На основе времени (TOTP) - + Counter-based (HOTP) На основе счетчика (HOTP) - + Steam Guard Steam Guard - + Title Заголовок - + Title for the OTP Заголовок для OTP - + Secret (at least 16 characters) Секрет (минимум 16 символов) - + Secret OTP Key Секретный ключ OTP - + Length Длина - + Length of the Token Длина токена - - + + Time Derivation (Seconds) Интервал расхождения (секунд) - + Next Counter Value Следующее значение счетчика - + Next Value of the Counter Следующее значение счетчика @@ -251,68 +252,79 @@ License: BSD (3-clause) MainView - + About О приложении - + Settings - Translated using Google Translate настройки - + Export / Import Экспорт / импорт - + Add Token Добавить токен - + Nothing here Ничего нету - + Pull down to add a OTP Потяните вниз чтобы добавить OTP - + Deleting Удаление - + + Token for Токен для - + + copied to clipboard скопирован в буфер обмена - - Move up - Передвинуть вверх + + Copy to Clipboard + Скопировать в буфер обмена - - Move down + + Show Token as QR-Code + Показать QR-код + + + + Move up Передвинуть вниз - + + Move down + Передвинуть вверх + + + Edit Редактировать - + Delete Удалить @@ -321,8 +333,9 @@ License: BSD (3-clause) QRPage - Can't create QR-Code from incomplete settings! - Не удалось создать QR-код из-за неполных настроек! + Can't create QR-Code from an empty String + Google Translate + Не удается создать QR-код из пустой строки @@ -348,12 +361,12 @@ License: BSD (3-clause) Сканирование... - + No valid Token data found. Не найдено корректных данных для токена. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Нажмите на изображение чтобы начать / остановить сканирование. Потяните вниз чтобы добавить токен вручную. @@ -368,14 +381,20 @@ License: BSD (3-clause) Behaviour - Translated using Google Translate - поведение + Google Translate + Поведение - Show Token as QRCode on Tap - Translated using Google Translate - Сенсорный токен как QR-код + Show Token as QR on Tap + Google Translate + Показать токен как QR на кране + + + + Hide Tokens and Reveal on Tap + Google Translate + Скрыть токены и показать на кране diff --git a/translations/harbour-sailotp-sv.ts b/translations/harbour-sailotp-sv.ts index fbbd443..5d6fc45 100644 --- a/translations/harbour-sailotp-sv.ts +++ b/translations/harbour-sailotp-sv.ts @@ -47,82 +47,83 @@ Licens: BSD (3-clause) + Can't create QR-Code from incomplete settings! Kan inte skapa QR-kod från ofullständiga inställningar! - - Save - Spara - - - + Add Lägg till - + + Save + Spara + + + Type Typ - + Time-based (TOTP) Tidsbaserad (TOTP) - + Counter-based (HOTP) Räknarbaserad (HOTP) - + Steam Guard Steam Guard - + Title Namn - + Title for the OTP Namn på OTP:n - + Secret (at least 16 characters) Hemlighet (Minst 16 tecken) - + Secret OTP Key Hemlig OTP-nyckel - + Length längd - + Length of the Token Längden av token - - + + Time Derivation (Seconds) Tidsavvikelsen (sekunder) - + Next Counter Value Nästa räknarvärde - + Next Value of the Counter Nästa värde på räknaren @@ -251,68 +252,79 @@ Licens: BSD (3-clause) MainView - + About Om - + Settings - Translated using Google Translate Inställningar - + Export / Import Export / Import - + Add Token Lägg till Token - + Nothing here Inget här - + Pull down to add a OTP Dra neråt för att lägga till en OTP - + Deleting Tar bort - + + Token for Token för - + + copied to clipboard - kopierad till urklipp + kopierad till urklipp - + + Copy to Clipboard + Kopiera till Urklipp + + + + Show Token as QR-Code + Visa QR-kod + + + Move up Flytta upp - + Move down Flytta ner - + Edit Redigera - + Delete Ta bort @@ -321,8 +333,9 @@ Licens: BSD (3-clause) QRPage - Can't create QR-Code from incomplete settings! - Kan inte skapa QR-kod från ofullständiga inställningar! + Can't create QR-Code from an empty String + Google Translate + Kan inte skapa QR-kod från en tom sträng @@ -348,12 +361,12 @@ Licens: BSD (3-clause) Skannar... - + No valid Token data found. Ingen giltig Token-data hittades. - + Tap the picture to start / stop scanning. Pull down to add Token manually. Tryck på bilden för att starta / stoppa skanning. Dra neråt för att lägga till Token manuellt. @@ -368,14 +381,20 @@ Licens: BSD (3-clause) Behaviour - Translated using Google Translate + Google Translate Beteende - Show Token as QRCode on Tap - Translated using Google Translate - Peka token som en QR-kod + Show Token as QR on Tap + Google Translate + Visa Token som QR på kran + + + + Hide Tokens and Reveal on Tap + Google Translate + Dölj tokens och avslöja på kranen diff --git a/translations/harbour-sailotp-zh_CN.ts b/translations/harbour-sailotp-zh_CN.ts index d8db44a..e34e1c3 100644 --- a/translations/harbour-sailotp-zh_CN.ts +++ b/translations/harbour-sailotp-zh_CN.ts @@ -46,82 +46,83 @@ License: BSD (3-clause) + Can't create QR-Code from incomplete settings! 不能从未完成的设置中创建二维码 - - Save - 保存 - - - + Add 添加 - + + Save + 保存 + + + Type 类型 - + Time-based (TOTP) 基于时间(TOTP) - + Counter-based (HOTP) 基于计数器(HOTP) - + Steam Guard 时间流守卫 - + Title 标题 - + Title for the OTP OTP的标题 - + Secret (at least 16 characters) 密码(至少16个字符) - + Secret OTP Key OTP密钥 - + Length 长度 - + Length of the Token 令牌的长度 - - + + Time Derivation (Seconds) 时间推导(秒) - + Next Counter Value 下一个计数器的值 - + Next Value of the Counter 下一个计数器的值 @@ -249,67 +250,79 @@ License: BSD (3-clause) MainView - + About 关于 - + Settings 设置 - + Export / Import 导出/导入 - + Add Token 添加令牌 - + Nothing here 无内容 - + Pull down to add a OTP 下拉添加一个OTP - + Deleting 删除中 - + + Token for 令牌 - + + copied to clipboard 已复制到剪切板 - + + Copy to Clipboard + 复制到剪贴板 + + + + Show Token as QR-Code + 显示二维码 + + + Move up 向上 - + Move down 向下 - + Edit 编辑 - + Delete 删除 @@ -318,8 +331,9 @@ License: BSD (3-clause) QRPage - Can't create QR-Code from incomplete settings! - 不能重未完成的设置中创建二维码 + Can't create QR-Code from an empty String + Google Translate + 无法从空字符串创建QR码 @@ -345,12 +359,12 @@ License: BSD (3-clause) 扫描中... - + No valid Token data found. 没有发现有效的令牌数据。 - + Tap the picture to start / stop scanning. Pull down to add Token manually. 点击照片开始/结束扫描,下拉手动添加 @@ -365,12 +379,20 @@ License: BSD (3-clause) Behaviour + Google Translate 行为 - Show Token as QRCode on Tap - 点击后显示令牌为二维码 + Show Token as QR on Tap + Google Translate + 在点击时将令牌显示为QR + + + + Hide Tokens and Reveal on Tap + Google Translate + 隐藏令牌并在点击时显示 diff --git a/translations/harbour-sailotp.ts b/translations/harbour-sailotp.ts index fd1a26d..2b1f760 100644 --- a/translations/harbour-sailotp.ts +++ b/translations/harbour-sailotp.ts @@ -41,88 +41,89 @@ License: BSD (3-clause) Show QR-Code - Show QR-Code + + Can't create QR-Code from incomplete settings! - Can't create QR-Code from incomplete settings! + - - Save - - - - + Add - + - + + Save + + + + Type - + - + Time-based (TOTP) - + - + Counter-based (HOTP) - + - + Steam Guard - Steam Guard + - + Title - - - - - Title for the OTP - + - Secret (at least 16 characters) - + Title for the OTP + - - Secret OTP Key - + + Secret (at least 16 characters) + - Length - Length - - - - Length of the Token - Length of the Token + Secret OTP Key + + Length + + + - Time Derivation (Seconds) - Time Derivation (Seconds) + Length of the Token + - Next Counter Value - + + Time Derivation (Seconds) + - + + Next Counter Value + + + + Next Value of the Counter - + @@ -248,77 +249,89 @@ License: BSD (3-clause) MainView - + About - + - + Settings - + - + Export / Import - + - + Add Token - + - + Nothing here - + - + Pull down to add a OTP - + - + Deleting - + - + + Token for - + - + + copied to clipboard - + - + + Copy to Clipboard + + + + + Show Token as QR-Code + + + + Move up - Move up + - + Move down - Move down + - + Edit - + - + Delete - + QRPage - Can't create QR-Code from incomplete settings! - Can't create QR-Code from incomplete settings! + Can't create QR-Code from an empty String + @@ -344,12 +357,12 @@ License: BSD (3-clause) - + No valid Token data found. - + Tap the picture to start / stop scanning. Pull down to add Token manually. @@ -359,17 +372,22 @@ License: BSD (3-clause) Settings - + Behaviour - + - Show Token as QRCode on Tap - + Show Token as QR on Tap + + + + + Hide Tokens and Reveal on Tap +