From b77b8b1619b5e8cffeec29e4118883ac2439c67e Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 25 Jan 2026 16:21:07 +0000 Subject: [PATCH] adding variviction --- config/__pycache__/settings.cpython-311.pyc | Bin 6773 -> 6800 bytes config/settings.py | 1 + core/__pycache__/forms.cpython-311.pyc | Bin 19892 -> 20174 bytes core/__pycache__/models.cpython-311.pyc | Bin 17428 -> 17498 bytes core/__pycache__/urls.cpython-311.pyc | Bin 2487 -> 2592 bytes core/__pycache__/views.cpython-311.pyc | Bin 19641 -> 22573 bytes core/forms.py | 1 + .../0014_alter_otpverification_purpose.py | 18 + ...er_otpverification_purpose.cpython-311.pyc | Bin 0 -> 1010 bytes core/models.py | 1 + core/templates/core/edit_profile.html | 9 +- core/templates/core/login.html | 9 +- core/templates/core/register.html | 119 ++- core/templates/core/shipment_request.html | 7 + core/templates/core/verify_otp.html | 9 +- core/templates/core/verify_registration.html | 53 ++ core/urls.py | 1 + core/views.py | 69 +- locale/ar/LC_MESSAGES/django.mo | Bin 13427 -> 15481 bytes locale/ar/LC_MESSAGES/django.po | 871 ++++++++++-------- 20 files changed, 749 insertions(+), 419 deletions(-) create mode 100644 core/migrations/0014_alter_otpverification_purpose.py create mode 100644 core/migrations/__pycache__/0014_alter_otpverification_purpose.cpython-311.pyc create mode 100644 core/templates/core/verify_registration.html diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index ae6ee69cd8a6f3d1b49a8b8f09893a5bc7d60588..ccdc8c4d0a111135c49875ea2313dcba4531670f 100644 GIT binary patch delta 114 zcmexrGQpI0IWI340}u#Vlx3co$ScWcv{7A;jWa6BHibEuK{I-D6k95f6l+d?dS>1& z&XmOBjHLX;qLf>#nRzLx6`FRNFA0?}adGjg>i=K{IM|99t@nFlS0)aYj;pVo}O1 z*37(=)Cx`8&3A=Lm?p=FI&n1swK4*6@$JnkM9;E_i7H%R5V|2Idx1e1f{FxzvH%P4 B9P9u9 diff --git a/config/settings.py b/config/settings.py index 62e5201..d104fa0 100644 --- a/config/settings.py +++ b/config/settings.py @@ -211,5 +211,6 @@ WHATSAPP_ENABLED = os.getenv("WHATSAPP_ENABLED", "true").lower() == "true" # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +LOGIN_URL = 'login' LOGIN_REDIRECT_URL = 'dashboard' LOGOUT_REDIRECT_URL = 'index' \ No newline at end of file diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index cbc72b448ce913f4352de8ea6a90fc5eb4fa903c..71902827d706d8b8f92ac3a4fb1cc2afb394519b 100644 GIT binary patch delta 2040 zcma)+Urbw79LMjubQj9Mjkc_%Q0N#a1;IHX3L_3Db}%R~5C+|}*52E4`FG*8!;K|W z4V&!2Kg)S=IN4@Y%pzGd*M}|f!N)~2QxYDQ`m~oNJ}hC$-h9yWy@i!En0eFtxxe%K zo%6fDp6~D6pRbTVmPz6F1qHbRzy55URjUsERCr$^5A+Qwmk=|n%PB7li*lYQD3YAN zLImLley6Um7!esU+gg>ZvBE8MqVox1$Cj6B6-7FJtR&f1O?w#cazmS?1}XQXhXQ^Yq@Sf7!iL==t+ zvTZ?-i&sQmAHO&2b1n*DBJW+u@t4Z>1;Jk?r#vMKX1{AuI79s91A?bCX&a0xv|ov+ z(HITJRBg(u(a9v6H;1xmEzd=rEKupF&K**y8b0fuRf9K7v=IRZP{NVSR;SdM8l2GY zn^m&wHSTh--aMIfu<_Os{cc``M7r6-q8j33do8^#FBTrcLMg0H#1xv`6;>&Ke+&1q z3zl|i05g0nVR4Xt_LrqqIu6GWtFu;;5!S<5sn1wnFp(g;YTuWqB02+5_M3f>9MRp5 zd6CSpYfiVt2Y)|sg2R(fhuNCbaUu#&4&diV7DSX-K%;>WRf4>tvk1%q8OtSVyzG61 z&HyMinVniDQ;oHi+T7>3Z?0sgjcteqXO&JCE4@c5n6Ios+N}D+vZ}f#?@Z?P2W3?o zP$ra6ENPv^&Z{9qoWP_K8`WfXv&_+qy6H*4s4)+Pn5MKTE+?G%0RA%V07ih*z&Z9$ zS+QH=W)!EVjUIsa;1&uHs1#YF>x;-eXWixMb!Xj=ky|sjW`4Ebp8I7k(RA#NKQUtb zPAY37;q{SlqC1jk98FBm;78}zrsM0=@eM)f6nn(Sc=$y=lEra6N+-le26=?r36ov_ z-Bo2GZ?KJh9@5U7m7c?`s0O_?x4VyOyh{{!pBjptrb?s@44@2C%FRkUH2QF#q44`A#R z^rD}!y9Y|!KZW@L@DWEcSBp(=w*IzmzJU109NYW&BAmdm-uTifkzCX-y=<4Z)V$g3 zuKye}o&zoc|0(Vj9=)pn-K>eELmzK_-W<=6@*0+Z1Elr5j^Wq9(|Xcx;roumW80=| zTDA<;yqKOLU4x*&6}@e5?b3JNmRYZt|qR4Lk1U63PIU znWIZ1OKh?0OUc;cC05hzB0BSS-)`z8#I_;q%*#z*9e!lQ9&ev9B(g(3C+qQr{{^RR B#7qDH delta 1892 zcma)*O-vg{6vuaLvtVNz3g)W`9|<4Ak#L)cs1YG00Rp52QbK^%NxL}SwOP7&>8v3% zYD1`eh|&*5odZo8(l%A8qHu|}QdRZTQ+vuOhiH4Kdg(Q()Kd;o=RXUvL#f)4{PWv4 zZ)V=S|C@Vjc3!L3+SY%i!ZEU#X*(y+eYw^OorGu7475%yH{~?PcNUOFL5|>N;k3^b&66t zwX#mJp3$>el5C)iSqz1ytQLD-%@sS%fh_?pe#gLEE*M~hn z5*BD!wM!aXe58kUG)Ku%HpO{}tu!|NR@0)Mi27(J&Z!0J zfHUl;KplI~{G<*gbcz$IN;S(WtR;KcQdL?|TUOS(Pd=n-HaFaQh!Lx4Eu64s^vxFZbB}1jd>2lz;aELcuxDc_Z)3h3$J-5l2pEtz!!W_Dhg)3P(BTF`1M2>yV>Drl-4oWPVl zdf=>wrNb@?Pa7Fyy1w(t8-euDxKXeWe5_u%;%+C(q==oF3 N{Z$xonvIOE{0*3nm7V|q diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index fdc0ec8f5af262b368cecfc7a0ff3665c14e49e7..d5259c313317d228f9807932e0f0b6f3c284e9e7 100644 GIT binary patch delta 292 zcmbQz!Fa2Kk#{*SFBbz4oVF>;{JoKPiVYVVhzkUtr6#Yov7Nj@N`fhkdGae8c}Dih zT()6V(bEUGRFs|XAoFynXd6KQLJ|7c9Dr*)$L^A_J3f~(3WsD3AtAQ8- zq6AU|S{R}PQv`z^Q{lvt9PpLdHV2#L3u*^Y;i@#16w`{j(! zC-1OVWV}83mc6m`4NmbHfX2L|lqgtRF+AHi~8aHuGf1v(l4#9L1z delta 240 zcmccB!8oOZk#{*SFBbz4xXP4ep4-Sf#b%-`CnMA3)i$=14+$u6tYKZo#K5qcY4Se- z39S^iHSEh6fm|SlfGBPzhE&!pun8cM6pmDu6vj22le28)nYq?*PwugmpWJCH#4C`( z*TN7bn8F{-peZoo&3gLk@4hYJ_lpY53J1MYz_V&I5x*P mtYc*Sw3*w9hsl|jF^KU419oyk+LWA+V7V_iR20bqody7-V>~KIWI340}!y-mSs+1V_H zm>C#W12F`oi$=+$7zZwnO3QPOBlk4he#A9mSpDV zZRTZ>XJV9{tjo5TsYrVAS+)sWdO+hCfw(wvayt8AkqeyCGeWP(nq9CBy1){AktO&F YOYmk@j%G%FeF=W125t~6(gCUm07dUK6aWAK delta 114 zcmZ1=vRznxIWI340}$M0EX%ZKV_JZYZ)ZQec``>GBfqXVKT`uY2o`Arr2qt;7nT43 diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 25218ec121aaf8163d746a4be1bc3b10870cb83e..3d1e86183a514e7571af7b6fad57e1388d9e024b 100644 GIT binary patch delta 4801 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 GjQDRv@L2l* delta 2623 zcmai0eQZ_kRrJlK(Mz-;8xRupwPSraj-9*W4 z64L`??21)wo`FwU3(13@mseZ5WYu#>Qd-L|Se9&XJXYCU$0X^RbV2&6X#-JZr!BPL z$Kh+SF>B8S27hscLKiJX=c*2FxL~=7YPW?d@tIVthR&_ckf`$4x}Vilt*Q+k?(}xq z_ZzkYV}}kKm1FaBL=kPB&{EyumZtQ;VD-YdU zmfTye+8#OGZx6mP`1;W7(6VH$R36ngT|=q z`nA{hdLGudE!DRzy4sc63k8iUjK?9|c#iFW8;!>s zgv`eC8I8M0O`b?+FiPbJkAPuMrBa%%^DwcfFp8ab5xtLKKLJ$^D%OXc2a%xQ z^fe5Q2Ng)IUuH4r+UP51{fmqZLcArqRzxt2T6{Z#Vl^yjmG7YS2)xs>&H0Sq@W+;* zcPEL2T)5Uk%W zMinzt6b05A>iF!GAW1~Z#)(=@nPM}8KL!U{x7tsjEDu*&Z(*UjHlDN!<9ryoij|Ag zMIuMwrZUM4sB3?X^}~F7kR5@awQpg4@UQj}b_}+5T(B2#({#DqaSMwMg(hFQxH)KP z&LNi{BYT!-?Gbl7-0M2edSO#{6B^y!?e~rlTjVG}l<7UZ(!JiZYKFIw~ACg$8aP%D~xYu;O?ubo2DI?2reUFyUyW>FNI$v z&J1y^{55g} z#k8jLw}>O`uJ-n@ImfC_X~o2f*1M?n5nSnib0uF#2b$#bwDT;S8SuNWA^9;aUm>8B zCZ38bV=eMLa_>vf9b0Qwt*pf!u;AB`YuL4HGMzCTS!~(lDGg&KHvcxkci_O_Y%evd z;xb#`OYF~DKZHxemC9(zoTet!WHI^l5;@|27J+cQRlb2b4j1L`aphm=_ ztoSn9Np$8}`1#N}`TNNHM1m(nVJuSBaHGABoH1O5$$U;r3Qw8*vqU}eSVN2yzoVkT5UdZd3QI#(i z5?QS{nOBX9vy;i9o-7nf;Bhvy5^Q#c!ll}y8c$E8Q^{gFp9_rOZkn#u6PU_`j`KTL z%$zR;pwrnTi~M%NUw5@uh)nu<6g;Ee4m#KziDHWWfR>^czem&&a?7D(QSbn8y83;* zgZLuI4Mh0}&LF_FD-^ZSiqff6n75wJ5_ij})RPmMS)6;sq#175MK<9NqrLL4as5Op zdv<3nnDFU6E_J9*Wqo;!Q9+bRYa(m1hqY znEX@P`4LzS4_=~w8|DZ3AW`&%;WY3$jcPGC`AMQ^!f~2J{9OX-T|Q56gMh9-rLG-->P7ygHT9;{4CJq>-w>h&5lfGR7WBdz@2Vz1nniwSpgNMCLx}CSXUHi*vi@=G4 z2anvid(as9V~pWI=IV)C37k0jrn`#*cG_>=H}B1x_rB@3u`!$A^J`%(xUUiNTanRI z8yZIoXzUP9I1NceTQt&I8YLQeLAdsba2;r0A8q=I){j%x(z)@LIJE=ib~I^6L05Qr zki?lZql814`J8>iIUh#=18 zl_XEsKm?t@ulkYov=C{Mfum!h%cEUI%Do&mFTWXNnO?1U72##s$3$=@AcGtuhJ1QO zag1mR=muFnkV`gK{$b)0_Ixmb;OMgM_maSeOx8Jcydum|WpAB@5O?z)`t3?*7JCs$ zqrzGzfRHacmTa(UoiS-MhH(XU$YhhT4}}-1Sj9M`5OawA05YMjR@#eU4&u4WA`G=) zE%m$smv)lE@QS~aBXp9JRkxQ!;1=y7&I=dT!7uVexY+&sEcJYFmF(`{U&F-&2)ZU_@|SD=h+6JhIglqRvBl)5%yZoMjPVoiOv_ZpM?H)i**-P|9a*}k_o zK2s9%prxHduH|ZJQD4$=y8cW*tnj$PvTj)RAwf7+Q0nHmx%E;FF*Pb?*)gQW`(E5l z=6Ji(tI}vt?xYH5ApigX literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index dad3a39..35f9189 100644 --- a/core/models.py +++ b/core/models.py @@ -198,6 +198,7 @@ class OTPVerification(models.Model): PURPOSE_CHOICES = ( ('profile_update', _('Profile Update')), ('password_reset', _('Password Reset')), + ('registration', _('Registration')), ) user = models.ForeignKey(User, on_delete=models.CASCADE) code = models.CharField(max_length=6) diff --git a/core/templates/core/edit_profile.html b/core/templates/core/edit_profile.html index 49f4b42..0037256 100644 --- a/core/templates/core/edit_profile.html +++ b/core/templates/core/edit_profile.html @@ -8,6 +8,13 @@
+ + +

{% trans "Edit Profile" %}

@@ -91,4 +98,4 @@ document.addEventListener('DOMContentLoaded', function() { border-radius: 8px; } -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/login.html b/core/templates/core/login.html index 0d181ef..e00f40f 100644 --- a/core/templates/core/login.html +++ b/core/templates/core/login.html @@ -8,6 +8,13 @@
+ + +

{% trans "Login to masarX" %}

@@ -47,4 +54,4 @@ border-radius: 8px; } -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/register.html b/core/templates/core/register.html index 6985e83..b8a9a96 100644 --- a/core/templates/core/register.html +++ b/core/templates/core/register.html @@ -7,24 +7,33 @@
-
+
+ + +

{% trans "Join masarX" %}

{% csrf_token %} - {% for field in form %} -
- - {{ field }} - {% if field.help_text %} -
{{ field.help_text }}
- {% endif %} - {% if field.errors %} -
{{ field.errors }}
- {% endif %} -
- {% endfor %} +
+ {% for field in form %} +
+ + {{ field }} + {% if field.help_text %} +
{{ field.help_text }}
+ {% endif %} + {% if field.errors %} +
{{ field.errors }}
+ {% endif %} +
+ {% endfor %} +
@@ -43,47 +52,50 @@ document.addEventListener('DOMContentLoaded', function() { const governateSelect = document.getElementById('id_governate'); const citySelect = document.getElementById('id_city'); - countrySelect.addEventListener('change', function() { - const countryId = this.value; - governateSelect.innerHTML = ''; - citySelect.innerHTML = ''; - - if (countryId) { - fetch(`{% url 'get_governates' %}?country_id=${countryId}`) - .then(response => response.json()) - .then(data => { - data.forEach(gov => { - const option = document.createElement('option'); - option.value = gov.id; - option.textContent = gov.name; - governateSelect.appendChild(option); + // Only attach listeners if elements exist (safety check) + if (countrySelect && governateSelect && citySelect) { + countrySelect.addEventListener('change', function() { + const countryId = this.value; + governateSelect.innerHTML = ''; + citySelect.innerHTML = ''; + + if (countryId) { + fetch(`{% url 'get_governates' %}?country_id=${countryId}`) + .then(response => response.json()) + .then(data => { + data.forEach(gov => { + const option = document.createElement('option'); + option.value = gov.id; + option.textContent = gov.name; + governateSelect.appendChild(option); + }); }); - }); - } - }); + } + }); - governateSelect.addEventListener('change', function() { - const governateId = this.value; - citySelect.innerHTML = ''; - - if (governateId) { - fetch(`{% url 'get_cities' %}?governate_id=${governateId}`) - .then(response => response.json()) - .then(data => { - data.forEach(city => { - const option = document.createElement('option'); - option.value = city.id; - option.textContent = city.name; - citySelect.appendChild(option); + governateSelect.addEventListener('change', function() { + const governateId = this.value; + citySelect.innerHTML = ''; + + if (governateId) { + fetch(`{% url 'get_cities' %}?governate_id=${governateId}`) + .then(response => response.json()) + .then(data => { + data.forEach(city => { + const option = document.createElement('option'); + option.value = city.id; + option.textContent = city.name; + citySelect.appendChild(option); + }); }); - }); - } - }); + } + }); + } }); -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/core/templates/core/shipment_request.html b/core/templates/core/shipment_request.html index fe0d6b9..d86aa5b 100644 --- a/core/templates/core/shipment_request.html +++ b/core/templates/core/shipment_request.html @@ -6,6 +6,13 @@
+ + +

{% trans "Request a Shipment" %}

diff --git a/core/templates/core/verify_otp.html b/core/templates/core/verify_otp.html index 1a5b9a0..71d3309 100644 --- a/core/templates/core/verify_otp.html +++ b/core/templates/core/verify_otp.html @@ -8,6 +8,13 @@
+ + +

{% trans "Verification Required" %}

@@ -44,4 +51,4 @@ letter-spacing: 0.5em; } -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/core/templates/core/verify_registration.html b/core/templates/core/verify_registration.html new file mode 100644 index 0000000..c35a57b --- /dev/null +++ b/core/templates/core/verify_registration.html @@ -0,0 +1,53 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% trans "Verify Account" %} | masarX{% endblock %} + +{% block content %} +
+
+
+
+ + + +
+
+

{% trans "Account Verification" %}

+

+ {% trans "We have sent a verification code to verify your account. Please enter it below to complete registration." %} +

+ + {% csrf_token %} +
+ + +
+
+ +
+ +
+
+
+
+
+
+ + +{% endblock %} diff --git a/core/urls.py b/core/urls.py index 99cc6e9..dc3c824 100644 --- a/core/urls.py +++ b/core/urls.py @@ -7,6 +7,7 @@ urlpatterns = [ path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(next_page='/'), name='logout'), path('register/', views.register, name='register'), + path('register/verify/', views.verify_registration, name='verify_registration'), path('dashboard/', views.dashboard, name='dashboard'), path('shipment-request/', views.shipment_request, name='shipment_request'), path('accept-parcel//', views.accept_parcel, name='accept_parcel'), diff --git a/core/views.py b/core/views.py index 8b1e65a..3ac78ad 100644 --- a/core/views.py +++ b/core/views.py @@ -43,13 +43,76 @@ def register(request): if request.method == 'POST': form = UserRegistrationForm(request.POST) if form.is_valid(): - user = form.save() - login(request, user) - return redirect('dashboard') + # Save user but inactive + user = form.save(commit=True) + user.is_active = False + user.save() + + # Generate OTP + code = ''.join(random.choices(string.digits, k=6)) + OTPVerification.objects.create(user=user, code=code, purpose='registration') + + # Send OTP + method = form.cleaned_data.get('verification_method', 'email') + if method == 'whatsapp': + phone = user.profile.phone_number + send_whatsapp_message(phone, f"Your verification code is: {code}") + messages.info(request, _("Verification code sent to WhatsApp.")) + else: + send_mail( + _('Verification Code'), + f'Your verification code is: {code}', + settings.DEFAULT_FROM_EMAIL, + [user.email], + fail_silently=False, + ) + messages.info(request, _("Verification code sent to email.")) + + request.session['registration_user_id'] = user.id + return redirect('verify_registration') else: form = UserRegistrationForm() return render(request, 'core/register.html', {'form': form}) +def verify_registration(request): + if 'registration_user_id' not in request.session: + messages.error(request, _("Session expired or invalid.")) + return redirect('register') + + if request.method == 'POST': + code = request.POST.get('code') + user_id = request.session['registration_user_id'] + try: + user = User.objects.get(id=user_id) + otp = OTPVerification.objects.filter( + user=user, + code=code, + purpose='registration', + is_verified=False + ).latest('created_at') + + if otp.is_valid(): + # Activate User + user.is_active = True + user.save() + + # Cleanup + otp.is_verified = True + otp.save() + del request.session['registration_user_id'] + + # Login + login(request, user) + + messages.success(request, _("Account verified successfully!")) + return redirect('dashboard') + else: + messages.error(request, _("Invalid or expired code.")) + except (User.DoesNotExist, OTPVerification.DoesNotExist): + messages.error(request, _("Invalid code.")) + + return render(request, 'core/verify_registration.html') + @login_required def dashboard(request): # Ensure profile exists diff --git a/locale/ar/LC_MESSAGES/django.mo b/locale/ar/LC_MESSAGES/django.mo index 146422a954e1b2f0c95eac2e937ae55b2528237c..3ef0a4ce0f3e6a9c5fd325c9f6dcf17ac68fc656 100644 GIT binary patch delta 6251 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 Pg9Cm4X;*mTsCWMZkRt|E delta 4325 zcmYk<3vg7`9mnyrAp#nNWRpNpz)eVi2nhisBnT;(gopBorY$7}Arc^=c_1MH1X+k7 zhG?zj@<x5NPA?0v@E!F5r5ag_EkW;&K39~0oK2Y!s)YR+IBUc?0a z2gc&}$j8J+8^gy8=IefZ%$kF=<2TbNbmu|=M&cagW9IRthAL1UZo~(0GmgQns0Kf= z*Dqmj>Q_+rePyqIW4((#Io~tJZ9fK+=-(t!c#sSE_Clex1ihTEK_#OR`{Gu6y&Zc| z{{WSV)9AwsI0J8D7EYuQO|TXQGCu1vT;=s3mv{)zLmw zgGW#U{1A2jS$q8=YAOC^um2NMsNbiJjW$-idM!U?6S4b|~`_J(8V zqy7mhrC-_e|FK5Ws!|z?%1pAYk4D{}i|S}LCgQWG0c=2Jy3ucMXhyAVD{6*+z=!d? ztzSoV^fjuZNH%~P_M#e0L_L>^>UcEjz8q9$XCT|fEJS6v+Ftjsrl65DpdQ?g>S#BH zHy>&VPN6o}B}~E_n2xjq1D%Jue<^Cyu0*ALJ=S6?uJRZ&hz<1u_3eY)c4KH% zduFIL6a8v9pMnp|kdJBNOEW!S{Q#Ab^Qg`A7t{c5pa%3Us^M-vw;eAs1~Ueg>H_OR zETq01_1y1$R&Nn11YFJ|;8C@4lCFsbz3tEtcXzEXR1#qqV9-HLw{qusx`~avZh0KSZth zpHLI}0yXoSr~&KeE*&01wKE-+;SxUujl32o;A^M{&Y(KFYQ2MMIELR*Jva#UTn6%@ zm}#gzP>i~-$zI=qTAD+sfu2OQdjWNy|0)Hg=$5_k9V&&fL)_Gl#4*%!aT>0|ad-+@ zcJnQ2Knd(rweu);$FZm%viF;s>+Q4L2kJ;q|vQK_GUn!pm&KiS_Igfe^ z{*FGpiP}stBi#EEQ5hRy%|SI-fSO^cwGOq}-arlPC>G#l9FIek|DF_zDd@pvs9job z>j6~5=a8hBtEkNM;U*0<3438CYR0*!cFM6gHlSv_4K;vv>uJoUel4B#*AGSFNPc`U z2eo-4;BGC(wgGCz^-~qMX=6mkzH>cn7~gd4;WS#P@AkOUGMiHW7V@5rnc^N$e(mO%xI@5hU8| z(@?Y#Sl;m8=9ySbJV$gLS~tC(UB`PA_*a;DjaW)(9q&CRQ8`4U652ERSuZ8Jjvr81 zL$H_K`LDtURk6oBeAAX&a5nJ{@wPp;0AIG{Wtd6mtvNt65YH1j^d{)g2Ax98AjT8h ziNiz*;n%LsC*CE-5j%;Y#10~sh$ikM#uC-U7DC4mLT^SJ5g_zO=qch2qM4XX93gZ} zcL{&Lcu$$4Km4Bl*q%(m9}&MIb`ifJwh=mhLOdBR@!H@o3I4j8SM0ebaK0^9VVo@s zUia`Z%_>^MWk3JfpwLb{8$RKFy$6De#5&?>VlAVwBZ4WY(hYpB8SRUg_E36UoWW_2j%j zN6NB@K-w^`C%!G%5p4JADPQnNup`tEYz-c8vQq~*6{*R+c>FLow9(WnfnBLjc$~!H zeFNQx?~HIhOY=Gx(~de9(kBEGMrL~g&t*h;0&7Oy>NbF=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +#: core/admin.py:18 core/models.py:84 +msgid "Profiles" +msgstr "الملفات الشخصية" + +#: core/admin.py:30 +msgid "General Info" +msgstr "معلومات عامة" + +#: core/admin.py:33 +msgid "Policies" +msgstr "السياسات" + +#: core/admin.py:36 +msgid "Payment Configuration" +msgstr "إعدادات الدفع" + +#: core/admin.py:39 +msgid "WhatsApp Configuration (Wablas Gateway)" +msgstr "إعدادات واتساب (بوابة Wablas)" + +#: core/admin.py:41 +msgid "" +"Configure your Wablas API connection. Use \"Test WhatsApp Configuration\" to " +"verify." +msgstr "قم بتكوين اتصال Wablas API الخاص بك. استخدم \"اختبار إعدادات واتساب\" للتحقق." + +#: core/admin.py:108 +msgid "Test WhatsApp" +msgstr "اختبار واتساب" + +#: core/admin.py:110 +#, fuzzy +#| msgid "Email" +msgid "Test Email" +msgstr "البريد الإلكتروني" + +#: core/admin.py:112 +msgid "Actions" +msgstr "إجراءات" + +#: core/admin.py:123 +msgid "Tools" +msgstr "أدوات" + #: core/forms.py:8 msgid "Name" msgstr "الاسم" @@ -26,7 +70,8 @@ msgstr "الاسم" msgid "Your Name" msgstr "اسمك" -#: core/forms.py:9 core/forms.py:28 +#: core/forms.py:9 core/forms.py:28 core/forms.py:90 core/forms.py:97 +#: core/templates/core/profile.html:41 msgid "Email" msgstr "البريد الإلكتروني" @@ -58,19 +103,21 @@ msgstr "تأكيد كلمة المرور" msgid "Register as" msgstr "التسجيل كـ" -#: core/forms.py:17 core/models.py:69 core/models.py:154 +#: core/forms.py:17 core/forms.py:92 core/models.py:71 core/models.py:158 msgid "Phone Number" msgstr "رقم الهاتف" -#: core/forms.py:19 core/models.py:23 core/models.py:27 core/models.py:71 +#: core/forms.py:19 core/forms.py:112 core/models.py:25 core/models.py:29 +#: core/models.py:75 msgid "Country" msgstr "الدولة" -#: core/forms.py:20 core/models.py:41 core/models.py:45 core/models.py:72 +#: core/forms.py:20 core/forms.py:113 core/models.py:43 core/models.py:47 +#: core/models.py:76 msgid "Governate" msgstr "المحافظة" -#: core/forms.py:21 core/models.py:59 core/models.py:73 +#: core/forms.py:21 core/forms.py:114 core/models.py:61 core/models.py:77 msgid "City" msgstr "المدينة" @@ -78,11 +125,11 @@ msgstr "المدينة" msgid "Username" msgstr "اسم المستخدم" -#: core/forms.py:29 +#: core/forms.py:29 core/forms.py:88 msgid "First Name" msgstr "الاسم الأول" -#: core/forms.py:30 +#: core/forms.py:30 core/forms.py:89 msgid "Last Name" msgstr "اسم العائلة" @@ -90,318 +137,388 @@ msgstr "اسم العائلة" msgid "Passwords don't match" msgstr "كلمات المرور غير متطابقة" -#: core/forms.py:97 -msgid "What are you sending?" -msgstr "ماذا سترسل؟" - -#: core/forms.py:104 core/forms.py:109 -msgid "Street/Building" -msgstr "الشارع/المبنى" - -#: core/forms.py:115 -msgid "Package Description" -msgstr "وصف الطرد" - -#: core/forms.py:116 core/models.py:112 -msgid "Weight (kg)" -msgstr "الوزن (كجم)" - -#: core/forms.py:117 -msgid "Shipping Price (OMR)" -msgstr "سعر الشحن (ر.ع)" - -#: core/forms.py:118 core/models.py:116 -msgid "Pickup Country" -msgstr "دولة الاستلام" - -#: core/forms.py:119 core/models.py:117 -msgid "Pickup Governate" -msgstr "محافظة الاستلام" - -#: core/forms.py:120 core/models.py:118 -msgid "Pickup City" -msgstr "مدينة الاستلام" - -#: core/forms.py:121 -msgid "Pickup Address (Street/Building)" -msgstr "عنوان الاستلام (الشارع/المبنى)" - -#: core/forms.py:122 core/models.py:122 -msgid "Delivery Country" -msgstr "دولة التوصيل" - -#: core/forms.py:123 core/models.py:123 -msgid "Delivery Governate" -msgstr "محافظة التوصيل" - -#: core/forms.py:124 core/models.py:124 -msgid "Delivery City" -msgstr "مدينة التوصيل" - -#: core/forms.py:125 -msgid "Delivery Address (Street/Building)" -msgstr "عنوان التوصيل (الشارع/المبنى)" - -#: core/forms.py:126 core/models.py:127 -msgid "Receiver Name" -msgstr "اسم المستلم" - -#: core/forms.py:127 core/models.py:128 -msgid "Receiver Phone" -msgstr "هاتف المستلم" - -#: core/models.py:10 core/models.py:28 core/models.py:46 -msgid "Name (English)" -msgstr "الاسم (إنجليزي)" - -#: core/models.py:11 core/models.py:29 core/models.py:47 -msgid "Name (Arabic)" -msgstr "الاسم (عربي)" - -#: core/models.py:24 -msgid "Countries" -msgstr "الدول" - -#: core/models.py:42 -msgid "Governates" -msgstr "المحافظات" - -#: core/models.py:60 -msgid "Cities" -msgstr "المدن" - -#: core/models.py:64 core/models.py:108 -msgid "Shipper" -msgstr "شاحن" - -#: core/models.py:65 -msgid "Car Owner" -msgstr "صاحب سيارة" - -#: core/models.py:67 -msgid "User" -msgstr "مستخدم" - -#: core/models.py:68 -msgid "Role" -msgstr "الدور" - -#: core/models.py:79 -msgid "Profile" -msgstr "الملف الشخصي" - -#: core/models.py:80 -msgid "Profiles" -msgstr "الملفات الشخصية" - -#: core/models.py:94 -msgid "Pending Pickup" -msgstr "في انتظار الاستلام" - -#: core/models.py:95 -msgid "Picked Up" -msgstr "تم الاستلام" - -#: core/models.py:96 -msgid "In Transit" -msgstr "في الطريق" - -#: core/models.py:97 -msgid "Delivered" -msgstr "تم التوصيل" - -#: core/models.py:98 -msgid "Cancelled" -msgstr "ملغي" - -#: core/models.py:102 -msgid "Pending" -msgstr "قيد الانتظار" - -#: core/models.py:103 -msgid "Paid" -msgstr "مدفوع" - -#: core/models.py:104 -msgid "Failed" -msgstr "فشل" - -#: core/models.py:107 -msgid "Tracking Number" -msgstr "رقم التتبع" - -#: core/models.py:109 core/templates/core/shipper_dashboard.html:42 -msgid "Carrier" -msgstr "الناقل" - -#: core/models.py:111 -msgid "Description" -msgstr "الوصف" - -#: core/models.py:112 -msgid "Weight in kg" -msgstr "الوزن بالكيلوجرام" - -#: core/models.py:113 -msgid "Price (OMR)" -msgstr "السعر (ر.ع)" - -#: core/models.py:119 -msgid "Pickup Address" -msgstr "عنوان الاستلام" - -#: core/models.py:125 -msgid "Delivery Address" -msgstr "عنوان التوصيل" - -#: core/models.py:130 core/templates/core/index.html:30 -msgid "Status" -msgstr "الحالة" - -#: core/models.py:131 -msgid "Payment Status" -msgstr "حالة الدفع" - -#: core/models.py:132 -msgid "Thawani Session ID" -msgstr "معرف جلسة ثواني" - -#: core/models.py:134 -msgid "Created At" -msgstr "أنشئ في" - -#: core/models.py:135 -msgid "Updated At" -msgstr "حدث في" - -#: core/models.py:146 -msgid "Parcel" -msgstr "طرد" - -#: core/models.py:147 -msgid "Parcels" -msgstr "طرود" - -#: core/models.py:150 -msgid "Platform Name" -msgstr "اسم المنصة" - -#: core/models.py:151 -msgid "Logo" -msgstr "الشعار" - -#: core/models.py:152 -msgid "Slogan" -msgstr "الشعار اللفظي" - -#: core/models.py:153 +#: core/forms.py:93 core/models.py:73 core/models.py:157 +#: core/templates/core/profile.html:59 msgid "Address" msgstr "العنوان" +#: core/forms.py:94 core/models.py:72 +msgid "Profile Picture" +msgstr "الصورة الشخصية" + +#: core/forms.py:97 +msgid "WhatsApp" +msgstr "واتساب" + +#: core/forms.py:98 +msgid "Verify changes via" +msgstr "التحقق من التغييرات عبر" + +#: core/forms.py:166 +msgid "What are you sending?" +msgstr "ماذا سترسل؟" + +#: core/forms.py:173 core/forms.py:178 +msgid "Street/Building" +msgstr "الشارع/المبنى" + +#: core/forms.py:184 +msgid "Package Description" +msgstr "وصف الطرد" + +#: core/forms.py:185 core/models.py:116 +msgid "Weight (kg)" +msgstr "الوزن (كجم)" + +#: core/forms.py:186 +msgid "Shipping Price (OMR)" +msgstr "سعر الشحن (ر.ع)" + +#: core/forms.py:187 core/models.py:120 +msgid "Pickup Country" +msgstr "دولة الاستلام" + +#: core/forms.py:188 core/models.py:121 +msgid "Pickup Governate" +msgstr "محافظة الاستلام" + +#: core/forms.py:189 core/models.py:122 +msgid "Pickup City" +msgstr "مدينة الاستلام" + +#: core/forms.py:190 +msgid "Pickup Address (Street/Building)" +msgstr "عنوان الاستلام (الشارع/المبنى)" + +#: core/forms.py:191 core/models.py:126 +msgid "Delivery Country" +msgstr "دولة التوصيل" + +#: core/forms.py:192 core/models.py:127 +msgid "Delivery Governate" +msgstr "محافظة التوصيل" + +#: core/forms.py:193 core/models.py:128 +msgid "Delivery City" +msgstr "مدينة التوصيل" + +#: core/forms.py:194 +msgid "Delivery Address (Street/Building)" +msgstr "عنوان التوصيل (الشارع/المبنى)" + +#: core/forms.py:195 core/models.py:131 +msgid "Receiver Name" +msgstr "اسم المستلم" + +#: core/forms.py:196 core/models.py:132 +msgid "Receiver Phone" +msgstr "هاتف المستلم" + +#: core/models.py:12 core/models.py:30 core/models.py:48 +msgid "Name (English)" +msgstr "الاسم (إنجليزي)" + +#: core/models.py:13 core/models.py:31 core/models.py:49 +msgid "Name (Arabic)" +msgstr "الاسم (عربي)" + +#: core/models.py:26 +msgid "Countries" +msgstr "الدول" + +#: core/models.py:44 +msgid "Governates" +msgstr "المحافظات" + +#: core/models.py:62 +msgid "Cities" +msgstr "المدن" + +#: core/models.py:66 core/models.py:112 +msgid "Shipper" +msgstr "شاحن" + +#: core/models.py:67 +msgid "Car Owner" +msgstr "صاحب سيارة" + +#: core/models.py:69 +msgid "User" +msgstr "مستخدم" + +#: core/models.py:70 +msgid "Role" +msgstr "الدور" + +#: core/models.py:83 +msgid "Profile" +msgstr "الملف الشخصي" + +#: core/models.py:98 +msgid "Pending Pickup" +msgstr "في انتظار الاستلام" + +#: core/models.py:99 +msgid "Picked Up" +msgstr "تم الاستلام" + +#: core/models.py:100 +msgid "In Transit" +msgstr "في الطريق" + +#: core/models.py:101 +msgid "Delivered" +msgstr "تم التوصيل" + +#: core/models.py:102 +msgid "Cancelled" +msgstr "ملغي" + +#: core/models.py:106 +msgid "Pending" +msgstr "قيد الانتظار" + +#: core/models.py:107 +msgid "Paid" +msgstr "مدفوع" + +#: core/models.py:108 +msgid "Failed" +msgstr "فشل" + +#: core/models.py:111 +msgid "Tracking Number" +msgstr "رقم التتبع" + +#: core/models.py:113 core/templates/core/shipper_dashboard.html:44 +msgid "Carrier" +msgstr "الناقل" + +#: core/models.py:115 +msgid "Description" +msgstr "الوصف" + +#: core/models.py:116 +msgid "Weight in kg" +msgstr "الوزن بالكيلوجرام" + +#: core/models.py:117 +msgid "Price (OMR)" +msgstr "السعر (ر.ع)" + +#: core/models.py:123 +msgid "Pickup Address" +msgstr "عنوان الاستلام" + +#: core/models.py:129 +msgid "Delivery Address" +msgstr "عنوان التوصيل" + +#: core/models.py:134 core/templates/core/index.html:30 +msgid "Status" +msgstr "الحالة" + +#: core/models.py:135 +msgid "Payment Status" +msgstr "حالة الدفع" + +#: core/models.py:136 +msgid "Thawani Session ID" +msgstr "معرف جلسة ثواني" + +#: core/models.py:138 +msgid "Created At" +msgstr "أنشئ في" + +#: core/models.py:139 +msgid "Updated At" +msgstr "حدث في" + +#: core/models.py:150 +msgid "Parcel" +msgstr "طرد" + +#: core/models.py:151 +msgid "Parcels" +msgstr "طرود" + +#: core/models.py:154 +msgid "Platform Name" +msgstr "اسم المنصة" + #: core/models.py:155 +msgid "Logo" +msgstr "الشعار" + +#: core/models.py:156 +msgid "Slogan" +msgstr "الشعار اللفظي" + +#: core/models.py:159 msgid "Registration Number" msgstr "رقم السجل التجاري" -#: core/models.py:156 +#: core/models.py:160 msgid "VAT Number" msgstr "الرقم الضريبي" -#: core/models.py:157 core/templates/base.html:177 -#: core/templates/core/privacy_policy.html:6 +#: core/models.py:161 core/templates/base.html:232 +#: core/templates/core/privacy_policy.html:11 msgid "Privacy Policy" msgstr "سياسة الخصوصية" -#: core/models.py:158 core/templates/core/terms_conditions.html:6 +#: core/models.py:162 core/templates/core/terms_conditions.html:11 msgid "Terms and Conditions" msgstr "الشروط والأحكام" -#: core/models.py:164 core/models.py:165 +#: core/models.py:165 +msgid "Wablas API Token" +msgstr "رمز Wablas API" + +#: core/models.py:165 +msgid "Your Wablas API Token." +msgstr "رمز Wablas API الخاص بك." + +#: core/models.py:166 +msgid "Wablas Domain" +msgstr "نطاق Wablas" + +#: core/models.py:166 +msgid "The Wablas API domain (e.g., https://deu.wablas.com)." +msgstr "نطاق Wablas API (مثال: https://deu.wablas.com)." + +#: core/models.py:167 +msgid "Wablas Secret Key" +msgstr "مفتاح Wablas السري" + +#: core/models.py:167 +msgid "Your Wablas API Secret Key (if required)." +msgstr "مفتاح Wablas API السري الخاص بك (إذا لزم الأمر)." + +#: core/models.py:170 +msgid "Enable Payment" +msgstr "تفعيل الدفع" + +#: core/models.py:170 +msgid "Toggle to enable or disable payments on the platform." +msgstr "تبديل لتفعيل أو تعطيل المدفوعات على المنصة." + +#: core/models.py:194 core/models.py:195 msgid "Platform Profile" msgstr "ملف تعريف المنصة" -#: core/templates/base.html:9 core/templates/base.html:149 +#: core/models.py:199 +msgid "Profile Update" +msgstr "تحديث الملف الشخصي" + +#: core/models.py:200 +msgid "Password Reset" +msgstr "إعادة تعيين كلمة المرور" + +#: core/templates/admin/core/platformprofile/test_email.html:11 +#: core/templates/admin/core/platformprofile/test_whatsapp.html:11 +msgid "Home" +msgstr "الرئيسية" + +#: core/templates/base.html:9 core/templates/base.html:204 msgid "Small Shipments, Smart Delivery" msgstr "شحنات صغيرة، توصيل ذكي" -#: core/templates/base.html:55 +#: core/templates/base.html:84 msgid "How it Works" msgstr "كيف يعمل" -#: core/templates/base.html:58 +#: core/templates/base.html:87 msgid "Contact" msgstr "اتصل بنا" -#: core/templates/base.html:62 +#: core/templates/base.html:92 msgid "Dashboard" msgstr "لوحة التحكم" -#: core/templates/base.html:66 -msgid "Admin" +#: core/templates/base.html:115 +#, fuzzy +#| msgid "Admin" +msgid "Admin Panel" msgstr "المسؤول" -#: core/templates/base.html:70 -msgid "Hello" -msgstr "مرحباً" +#: core/templates/base.html:118 core/templates/core/profile.html:4 +#: core/templates/core/profile.html:21 +msgid "My Profile" +msgstr "ملفي الشخصي" -#: core/templates/base.html:75 +#: core/templates/base.html:119 core/templates/core/edit_profile.html:4 +#: core/templates/core/edit_profile.html:20 core/templates/core/profile.html:23 +msgid "Edit Profile" +msgstr "تعديل الملف الشخصي" + +#: core/templates/base.html:124 msgid "Logout" msgstr "تسجيل الخروج" -#: core/templates/base.html:80 core/templates/core/login.html:4 -#: core/templates/core/login.html:25 +#: core/templates/base.html:132 core/templates/core/login.html:4 +#: core/templates/core/login.html:32 msgid "Login" msgstr "تسجيل الدخول" -#: core/templates/base.html:83 core/templates/core/register.html:4 +#: core/templates/base.html:135 core/templates/core/register.html:4 msgid "Register" msgstr "تسجيل" -#: core/templates/base.html:111 -msgid "Find Loads" -msgstr "البحث عن شحنات" - -#: core/templates/base.html:113 core/templates/core/index.html:13 +#: core/templates/base.html:164 core/templates/core/index.html:13 msgid "Start Shipping" msgstr "ابدأ الشحن" -#: core/templates/base.html:154 core/templates/core/contact.html:4 -#: core/templates/core/contact.html:14 +#: core/templates/base.html:209 core/templates/core/contact.html:4 +#: core/templates/core/contact.html:21 msgid "Contact Us" msgstr "اتصل بنا" -#: core/templates/base.html:163 +#: core/templates/base.html:218 msgid "Reg No:" msgstr "رقم السجل:" -#: core/templates/base.html:166 +#: core/templates/base.html:221 msgid "VAT No:" msgstr "الرقم الضريبي:" -#: core/templates/base.html:169 +#: core/templates/base.html:224 msgid "Send us a message" msgstr "أرسل لنا رسالة" -#: core/templates/base.html:175 +#: core/templates/base.html:230 msgid "Legal" msgstr "قانوني" -#: core/templates/base.html:178 +#: core/templates/base.html:233 msgid "Terms & Conditions" msgstr "الشروط والأحكام" -#: core/templates/base.html:186 +#: core/templates/base.html:241 msgid "All rights reserved." msgstr "جميع الحقوق محفوظة." -#: core/templates/core/contact.html:15 +#: core/templates/core/article_detail.html:10 +#: core/templates/core/contact.html:14 core/templates/core/login.html:14 +#: core/templates/core/privacy_policy.html:8 +#: core/templates/core/register.html:14 +#: core/templates/core/terms_conditions.html:8 +msgid "Back to Home" +msgstr "العودة إلى الصفحة الرئيسية" + +#: core/templates/core/article_detail.html:14 +msgid "Published on" +msgstr "نشر في" + +#: core/templates/core/contact.html:22 msgid "We'd love to hear from you. Please fill out the form below." msgstr "نود أن نسمع منك. يرجى ملء النموذج أدناه." -#: core/templates/core/contact.html:63 +#: core/templates/core/contact.html:70 msgid "Send Message" msgstr "إرسال الرسالة" -#: core/templates/core/contact.html:72 +#: core/templates/core/contact.html:79 msgid "Or reach us at" msgstr "أو تواصل معنا عبر" @@ -444,7 +561,7 @@ msgid "To" msgstr "إلى" #: core/templates/core/driver_dashboard.html:61 -#: core/templates/core/shipper_dashboard.html:41 +#: core/templates/core/shipper_dashboard.html:43 msgid "Receiver" msgstr "المستلم" @@ -456,6 +573,34 @@ msgstr "تحديث" msgid "You haven't accepted any shipments yet." msgstr "لم تقبل أي شحنات بعد." +#: core/templates/core/edit_profile.html:14 +msgid "Back to Profile" +msgstr "العودة إلى الملف الشخصي" + +#: core/templates/core/edit_profile.html:36 +#: core/templates/core/shipment_request.html:130 +#: core/templates/core/verify_otp.html:31 +msgid "Cancel" +msgstr "إلغاء" + +#: core/templates/core/edit_profile.html:37 +msgid "Save & Verify" +msgstr "حفظ وتحقق" + +#: core/templates/core/edit_profile.html:55 +#: core/templates/core/register.html:59 +#: core/templates/core/shipment_request.html:151 +msgid "Select Governate" +msgstr "اختر المحافظة" + +#: core/templates/core/edit_profile.html:56 +#: core/templates/core/edit_profile.html:74 +#: core/templates/core/register.html:60 core/templates/core/register.html:78 +#: core/templates/core/shipment_request.html:152 +#: core/templates/core/shipment_request.html:170 +msgid "Select City" +msgstr "اختر المدينة" + #: core/templates/core/index.html:10 msgid "Small Shipments," msgstr "شحنات صغيرة،" @@ -551,66 +696,68 @@ msgstr "لدي سيارة وأريد كسب المال" msgid "Become a Driver" msgstr "كن سائقاً" -#: core/templates/core/login.html:13 +#: core/templates/core/login.html:20 msgid "Login to masarX" msgstr "تسجيل الدخول إلى مسارX" -#: core/templates/core/login.html:28 +#: core/templates/core/login.html:35 msgid "Don't have an account?" msgstr "ليس لديك حساب؟" -#: core/templates/core/login.html:28 +#: core/templates/core/login.html:35 msgid "Register here" msgstr "سجل هنا" -#: core/templates/core/privacy_policy.html:11 +#: core/templates/core/privacy_policy.html:16 msgid "Privacy Policy not available yet." msgstr "سياسة الخصوصية غير متوفرة بعد." -#: core/templates/core/register.html:13 +#: core/templates/core/profile.html:14 +#: core/templates/core/shipment_request.html:12 +msgid "Back to Dashboard" +msgstr "العودة إلى لوحة التحكم" + +#: core/templates/core/profile.html:45 +msgid "Phone" +msgstr "الهاتف" + +#: core/templates/core/profile.html:49 +msgid "Location" +msgstr "الموقع" + +#: core/templates/core/register.html:20 msgid "Join masarX" msgstr "انضم إلى مسارX" -#: core/templates/core/register.html:28 +#: core/templates/core/register.html:37 msgid "Create Account" msgstr "إنشاء حساب" -#: core/templates/core/register.html:31 +#: core/templates/core/register.html:40 msgid "Already have an account?" msgstr "لديك حساب بالفعل؟" -#: core/templates/core/register.html:31 +#: core/templates/core/register.html:40 msgid "Login here" msgstr "سجل دخولك هنا" -#: core/templates/core/register.html:48 -#: core/templates/core/shipment_request.html:143 -msgid "Select Governate" -msgstr "اختر المحافظة" - -#: core/templates/core/register.html:49 core/templates/core/register.html:67 -#: core/templates/core/shipment_request.html:144 -#: core/templates/core/shipment_request.html:162 -msgid "Select City" -msgstr "اختر المدينة" - -#: core/templates/core/shipment_request.html:10 +#: core/templates/core/shipment_request.html:17 msgid "Request a Shipment" msgstr "طلب شحنة" -#: core/templates/core/shipment_request.html:39 +#: core/templates/core/shipment_request.html:46 msgid "Pickup Details" msgstr "تفاصيل الاستلام" -#: core/templates/core/shipment_request.html:72 +#: core/templates/core/shipment_request.html:79 msgid "Delivery Details" msgstr "تفاصيل التوصيل" -#: core/templates/core/shipment_request.html:105 +#: core/templates/core/shipment_request.html:112 msgid "Receiver Details" msgstr "تفاصيل المستلم" -#: core/templates/core/shipment_request.html:123 +#: core/templates/core/shipment_request.html:131 msgid "Submit Request" msgstr "إرسال الطلب" @@ -622,138 +769,132 @@ msgstr "شحناتي" msgid "New Shipment" msgstr "شحنة جديدة" -#: core/templates/core/shipper_dashboard.html:36 +#: core/templates/core/shipper_dashboard.html:37 msgid "Pay Now" msgstr "ادفع الآن" -#: core/templates/core/shipper_dashboard.html:42 +#: core/templates/core/shipper_dashboard.html:44 msgid "Waiting for pickup" msgstr "في انتظار الاستلام" -#: core/templates/core/shipper_dashboard.html:50 +#: core/templates/core/shipper_dashboard.html:52 msgid "You haven't sent any shipments yet." msgstr "لم ترسل أي شحنات بعد." -#: core/templates/core/shipper_dashboard.html:51 +#: core/templates/core/shipper_dashboard.html:53 msgid "Send your first shipment" msgstr "أرسل أول شحنة لك" -#: core/templates/core/terms_conditions.html:11 +#: core/templates/core/terms_conditions.html:16 msgid "Terms and Conditions not available yet." msgstr "الشروط والأحكام غير متوفرة بعد." -#: core/views.py:30 -msgid "Parcel not found." -msgstr "الطرد غير موجود." +#: core/templates/core/verify_otp.html:4 +msgid "Verify Profile Update" +msgstr "تحديث الملف الشخصي" -#: core/views.py:70 -msgid "Only shippers can request shipments." -msgstr "فقط الشاحنين يمكنهم طلب شحنات." +#: core/templates/core/verify_otp.html:14 +msgid "Back to Edit Profile" +msgstr "العودة إلى تعديل الملف الشخصي" -#: core/views.py:83 -msgid "Shipment requested successfully! Tracking ID: " -msgstr "تم طلب الشحنة بنجاح! رقم التتبع: " - -#: core/views.py:93 -msgid "Only car owners can accept shipments." -msgstr "فقط أصحاب السيارات يمكنهم قبول الشحنات." - -#: core/views.py:104 -msgid "You have accepted the shipment!" -msgstr "لقد قبلت الشحنة!" - -#: core/views.py:119 -msgid "Status updated successfully!" -msgstr "تم تحديث الحالة بنجاح!" - -#: core/views.py:138 -msgid "Could not initiate payment. Please try again later." -msgstr "تعذر بدء الدفع. يرجى المحاولة مرة أخرى لاحقاً." - -#: core/views.py:157 -msgid "Payment successful! Your shipment is now active." -msgstr "تم الدفع بنجاح! شحنتك نشطة الآن." - -#: core/views.py:159 -msgid "Payment status is pending or failed. Please check your dashboard." -msgstr "حالة الدفع معلقة أو فشلت. يرجى التحقق من لوحة التحكم." - -#: core/views.py:165 -msgid "Payment was cancelled." -msgstr "تم إلغاء الدفع." - -#: core/views.py:204 -msgid "Your message has been sent successfully!" -msgstr "تم إرسال رسالتك بنجاح!" - -#: core/views.py:206 -msgid "There was an error sending your message. Please try again later." -msgstr "حدث خطأ أثناء إرسال رسالتك. يرجى المحاولة مرة أخرى لاحقاً." - -#: core/forms.py:new -msgid "Profile Picture" -msgstr "الصورة الشخصية" - -#: core/forms.py:new -msgid "Verify changes via" -msgstr "التحقق من التغييرات عبر" - -#: core/templates/core/profile.html:new -msgid "My Profile" -msgstr "ملفي الشخصي" - -#: core/templates/core/profile.html:new -msgid "Edit Profile" -msgstr "تعديل الملف الشخصي" - -#: core/templates/core/edit_profile.html:new -msgid "Save & Verify" -msgstr "حفظ وتحقق" - -#: core/templates/core/verify_otp.html:new +#: core/templates/core/verify_otp.html:20 msgid "Verification Required" msgstr "التحقق مطلوب" -#: core/templates/core/verify_otp.html:new -msgid "We have sent a verification code to your selected contact method. Please enter it below to save your changes." -msgstr "لقد أرسلنا رمز التحقق إلى وسيلة الاتصال المحددة. يرجى إدخاله أدناه لحفظ تغييراتك." +#: core/templates/core/verify_otp.html:22 +msgid "" +"We have sent a verification code to your selected contact method. Please " +"enter it below to save your changes." +msgstr "" +"لقد أرسلنا رمز التحقق إلى وسيلة الاتصال المحددة. يرجى إدخاله أدناه لحفظ " +"تغييراتك." -#: core/templates/core/verify_otp.html:new +#: core/templates/core/verify_otp.html:27 core/views.py:267 msgid "Verification Code" msgstr "رمز التحقق" -#: core/templates/core/verify_otp.html:new +#: core/templates/core/verify_otp.html:32 msgid "Verify & Save" msgstr "تحقق وحفظ" -#: core/views.py:new -msgid "Profile updated successfully!" -msgstr "تم تحديث الملف الشخصي بنجاح!" +#: core/views.py:34 +msgid "Parcel not found." +msgstr "الطرد غير موجود." -#: core/views.py:new -msgid "Invalid or expired code." -msgstr "الرمز غير صالح أو منتهي الصلاحية." +#: core/views.py:74 +msgid "Only shippers can request shipments." +msgstr "فقط الشاحنين يمكنهم طلب شحنات." -#: core/views.py:new +#: core/views.py:87 +msgid "Shipment requested successfully! Tracking ID: " +msgstr "تم طلب الشحنة بنجاح! رقم التتبع: " + +#: core/views.py:97 +msgid "Only car owners can accept shipments." +msgstr "فقط أصحاب السيارات يمكنهم قبول الشحنات." + +#: core/views.py:108 +msgid "You have accepted the shipment!" +msgstr "لقد قبلت الشحنة!" + +#: core/views.py:123 +msgid "Status updated successfully!" +msgstr "تم تحديث الحالة بنجاح!" + +#: core/views.py:131 +msgid "Payments are currently disabled by the administrator." +msgstr "المدفوعات معطلة حالياً من قبل المسؤول." + +#: core/views.py:148 +msgid "Could not initiate payment. Please try again later." +msgstr "تعذر بدء الدفع. يرجى المحاولة مرة أخرى لاحقاً." + +#: core/views.py:167 +msgid "Payment successful! Your shipment is now active." +msgstr "تم الدفع بنجاح! شحنتك نشطة الآن." + +#: core/views.py:169 +msgid "Payment status is pending or failed. Please check your dashboard." +msgstr "حالة الدفع معلقة أو فشلت. يرجى التحقق من لوحة التحكم." + +#: core/views.py:175 +msgid "Payment was cancelled." +msgstr "تم إلغاء الدفع." + +#: core/views.py:214 +msgid "Your message has been sent successfully!" +msgstr "تم إرسال رسالتك بنجاح!" + +#: core/views.py:216 +msgid "There was an error sending your message. Please try again later." +msgstr "حدث خطأ أثناء إرسال رسالتك. يرجى المحاولة مرة أخرى لاحقاً." + +#: core/views.py:261 msgid "Verification code sent to WhatsApp." msgstr "تم إرسال رمز التحقق إلى واتساب." -#: core/views.py:new +#: core/views.py:273 msgid "Verification code sent to email." msgstr "تم إرسال رمز التحقق إلى البريد الإلكتروني." -#: core/views.py:new +#: core/views.py:320 +msgid "Profile updated successfully!" +msgstr "تم تحديث الملف الشخصي بنجاح!" + +#: core/views.py:323 msgid "Session expired. Please try again." msgstr "انتهت صلاحية الجلسة. يرجى المحاولة مرة أخرى." -#: core/views.py:new +#: core/views.py:326 +msgid "Invalid or expired code." +msgstr "الرمز غير صالح أو منتهي الصلاحية." + +#: core/views.py:328 msgid "Invalid code." msgstr "رمز غير صالح." -#: core/models.py:new -msgid "Profile Update" -msgstr "تحديث الملف الشخصي" +#~ msgid "Hello" +#~ msgstr "مرحباً" -#: core/models.py:new -msgid "Password Reset" -msgstr "إعادة تعيين كلمة المرور" +#~ msgid "Find Loads" +#~ msgstr "البحث عن شحنات" \ No newline at end of file