From 390c6ad77ec50f68ffe0833009aed3c6c734adb4 Mon Sep 17 00:00:00 2001 From: Spencer Fields <58378262+sgf36@users.noreply.github.com> Date: Mon, 28 Sep 2026 17:01:07 +0100 Subject: [PATCH 1/4] Bump version to 1.5.0 Co-Authored-By: Claude Opus 4.6 --- app/config.py | 2 +- packaging/msix/AppxManifest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config.py b/app/config.py index 1bc4a16..1198d9f 100644 --- a/app/config.py +++ b/app/config.py @@ -13,7 +13,7 @@ # (app/core/update_check.py) compares this against the latest GitHub release # tag to decide whether to prompt the user to update. Keep it in step with the # release tag and packaging/msix/AppxManifest.xml on every release. -APP_VERSION = "1.4.0" +APP_VERSION = "1.5.0" ICON_PATH = Path(__file__).parent / "resources" / "icons" / "app_icon.png" diff --git a/packaging/msix/AppxManifest.xml b/packaging/msix/AppxManifest.xml index 6cd76f8..a2319a8 100644 --- a/packaging/msix/AppxManifest.xml +++ b/packaging/msix/AppxManifest.xml @@ -9,7 +9,7 @@ From db119d2851a4c06772232eec56b28fe735fa2f31 Mon Sep 17 00:00:00 2001 From: Spencer Fields <58378262+sgf36@users.noreply.github.com> Date: Tue, 29 Sep 2026 00:03:15 +0100 Subject: [PATCH 2/4] Add smart dropdown filtering, inline recipient entry, and Click & Drop batch/history integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smart filtering: all address combo boxes across Create Shipment and Batch Import are now editable with substring-matching completers. Typing filters the dropdown in real time; focus-out restores the display to the current selection. Inline recipients: the To dropdown on Create Shipment has an "Enter new recipient…" sentinel at the bottom. Selecting it reveals an inline address form that passes the address directly to EasyPost or Click & Drop without requiring an address book entry. A "Save to address book" checkbox auto-saves after purchase. Click & Drop: batch CSV import now creates Click & Drop orders, history view shows void/manifest actions for CD shipments, and CD manifests produce locally-regenerated PDFs. Also adds alpha-3 country code conversion for Click & Drop and propagates three new i18n keys to all 50 locale files. Co-Authored-By: Claude Opus 4.6 --- app/core/countries.py | 55 ++++++ app/resources/locales/am.json | 10 ++ app/resources/locales/ar.json | 10 ++ app/resources/locales/bn.json | 10 ++ app/resources/locales/cs.json | 10 ++ app/resources/locales/de.json | 10 ++ app/resources/locales/el.json | 10 ++ app/resources/locales/en.json | 10 ++ app/resources/locales/es.json | 10 ++ app/resources/locales/fa.json | 10 ++ app/resources/locales/fr.json | 10 ++ app/resources/locales/gu.json | 10 ++ app/resources/locales/ha.json | 10 ++ app/resources/locales/he.json | 10 ++ app/resources/locales/hi.json | 10 ++ app/resources/locales/hr.json | 10 ++ app/resources/locales/hu.json | 10 ++ app/resources/locales/id.json | 10 ++ app/resources/locales/ig.json | 10 ++ app/resources/locales/it.json | 10 ++ app/resources/locales/ja.json | 10 ++ app/resources/locales/jv.json | 10 ++ app/resources/locales/kn.json | 10 ++ app/resources/locales/ko.json | 10 ++ app/resources/locales/ml.json | 10 ++ app/resources/locales/mr.json | 10 ++ app/resources/locales/ms.json | 10 ++ app/resources/locales/my.json | 10 ++ app/resources/locales/ne.json | 10 ++ app/resources/locales/nl.json | 10 ++ app/resources/locales/or.json | 10 ++ app/resources/locales/pa.json | 10 ++ app/resources/locales/pl.json | 10 ++ app/resources/locales/pt.json | 10 ++ app/resources/locales/ro.json | 10 ++ app/resources/locales/ru.json | 10 ++ app/resources/locales/si.json | 10 ++ app/resources/locales/so.json | 10 ++ app/resources/locales/sv.json | 10 ++ app/resources/locales/sw.json | 10 ++ app/resources/locales/ta.json | 10 ++ app/resources/locales/te.json | 10 ++ app/resources/locales/th.json | 10 ++ app/resources/locales/tr.json | 10 ++ app/resources/locales/uk.json | 10 ++ app/resources/locales/ur.json | 10 ++ app/resources/locales/uz.json | 10 ++ app/resources/locales/vi.json | 10 ++ app/resources/locales/yo.json | 10 ++ app/resources/locales/zh.json | 10 ++ app/resources/locales/zu.json | 10 ++ app/services/click_drop.py | 257 +++++++++++++++++++++++++-- app/services/shipments.py | 16 +- app/ui/views/batch_view.py | 157 +++++++++++++++- app/ui/views/create_shipment_view.py | 246 +++++++++++++++++++++---- app/ui/views/history_view.py | 108 +++++++++-- store_assets/RELEASE-NOTES-1.5.0.md | 47 +++++ 57 files changed, 1307 insertions(+), 79 deletions(-) create mode 100644 store_assets/RELEASE-NOTES-1.5.0.md diff --git a/app/core/countries.py b/app/core/countries.py index f9f6427..2646d79 100644 --- a/app/core/countries.py +++ b/app/core/countries.py @@ -103,3 +103,58 @@ def postal_label_kind_for(country_code: str) -> str: ] COUNTRIES = sorted(_RAW_COUNTRIES, key=lambda pair: pair[1]) + +_ALPHA2_TO_ALPHA3 = { + "AF": "AFG", "AL": "ALB", "DZ": "DZA", "AD": "AND", "AO": "AGO", + "AG": "ATG", "AR": "ARG", "AM": "ARM", "AU": "AUS", "AT": "AUT", + "AZ": "AZE", "BS": "BHS", "BH": "BHR", "BD": "BGD", "BB": "BRB", + "BY": "BLR", "BE": "BEL", "BZ": "BLZ", "BJ": "BEN", "BT": "BTN", + "BO": "BOL", "BA": "BIH", "BW": "BWA", "BR": "BRA", "BN": "BRN", + "BG": "BGR", "BF": "BFA", "BI": "BDI", "KH": "KHM", "CM": "CMR", + "CA": "CAN", "CV": "CPV", "CF": "CAF", "TD": "TCD", "CL": "CHL", + "CN": "CHN", "CO": "COL", "KM": "COM", "CG": "COG", "CD": "COD", + "CR": "CRI", "HR": "HRV", "CU": "CUB", "CY": "CYP", "CZ": "CZE", + "DK": "DNK", "DJ": "DJI", "DM": "DMA", "DO": "DOM", "EC": "ECU", + "EG": "EGY", "SV": "SLV", "GQ": "GNQ", "ER": "ERI", "EE": "EST", + "SZ": "SWZ", "ET": "ETH", "FJ": "FJI", "FI": "FIN", "FR": "FRA", + "GA": "GAB", "GM": "GMB", "GE": "GEO", "DE": "DEU", "GH": "GHA", + "GR": "GRC", "GD": "GRD", "GT": "GTM", "GN": "GIN", "GW": "GNB", + "GY": "GUY", "HT": "HTI", "HN": "HND", "HK": "HKG", "HU": "HUN", + "IS": "ISL", "IN": "IND", "ID": "IDN", "IR": "IRN", "IQ": "IRQ", + "IE": "IRL", "IL": "ISR", "IT": "ITA", "JM": "JAM", "JP": "JPN", + "JO": "JOR", "KZ": "KAZ", "KE": "KEN", "KI": "KIR", "KW": "KWT", + "KG": "KGZ", "LA": "LAO", "LV": "LVA", "LB": "LBN", "LS": "LSO", + "LR": "LBR", "LY": "LBY", "LI": "LIE", "LT": "LTU", "LU": "LUX", + "MO": "MAC", "MG": "MDG", "MW": "MWI", "MY": "MYS", "MV": "MDV", + "ML": "MLI", "MT": "MLT", "MH": "MHL", "MR": "MRT", "MU": "MUS", + "MX": "MEX", "FM": "FSM", "MD": "MDA", "MC": "MCO", "MN": "MNG", + "ME": "MNE", "MA": "MAR", "MZ": "MOZ", "MM": "MMR", "NA": "NAM", + "NR": "NRU", "NP": "NPL", "NL": "NLD", "NZ": "NZL", "NI": "NIC", + "NE": "NER", "NG": "NGA", "KP": "PRK", "MK": "MKD", "NO": "NOR", + "OM": "OMN", "PK": "PAK", "PW": "PLW", "PA": "PAN", "PG": "PNG", + "PY": "PRY", "PE": "PER", "PH": "PHL", "PL": "POL", "PT": "PRT", + "PR": "PRI", "QA": "QAT", "RO": "ROU", "RU": "RUS", "RW": "RWA", + "KN": "KNA", "LC": "LCA", "VC": "VCT", "WS": "WSM", "SM": "SMR", + "ST": "STP", "SA": "SAU", "SN": "SEN", "RS": "SRB", "SC": "SYC", + "SL": "SLE", "SG": "SGP", "SK": "SVK", "SI": "SVN", "SB": "SLB", + "SO": "SOM", "ZA": "ZAF", "KR": "KOR", "SS": "SSD", "ES": "ESP", + "LK": "LKA", "SD": "SDN", "SR": "SUR", "SE": "SWE", "CH": "CHE", + "SY": "SYR", "TW": "TWN", "TJ": "TJK", "TZ": "TZA", "TH": "THA", + "TL": "TLS", "TG": "TGO", "TO": "TON", "TT": "TTO", "TN": "TUN", + "TR": "TUR", "TM": "TKM", "TV": "TUV", "UG": "UGA", "UA": "UKR", + "AE": "ARE", "GB": "GBR", "US": "USA", "UY": "URY", "UZ": "UZB", + "VU": "VUT", "VA": "VAT", "VE": "VEN", "VN": "VNM", "YE": "YEM", + "ZM": "ZMB", "ZW": "ZWE", +} + + +def to_alpha3(alpha2: str) -> str: + """Convert an ISO 3166-1 alpha-2 code to alpha-3. + + Returns the input unchanged if it is already three characters or + if no mapping is found. + """ + code = (alpha2 or "").upper().strip() + if len(code) == 3: + return code + return _ALPHA2_TO_ALPHA3.get(code, code) diff --git a/app/resources/locales/am.json b/app/resources/locales/am.json index 6483f62..faff9cd 100644 --- a/app/resources/locales/am.json +++ b/app/resources/locales/am.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ዋጋዎችን አግኝ", "create_shipment.get_rates_error_body": "ዋጋዎችን ማግኘት አልተቻለም:\n{error}", "create_shipment.height_label": "ቁመት ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ለዋጋ መድን ግባ:", "create_shipment.insurance_none": "ምንም", "create_shipment.insurance_tooltip": "አማራጭ። ጥቅሉን ለመድን የሚያገለግል ዋጋ አስታውቅ፤ መያዣው የሚከፈለው መለያ ፊርማ ሲገዛ ነው።", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "በ«ተቀባይ» ውስጥ ጥቅሉ ለማን እንደሚላክ ይምረጡ።", "create_shipment.missing_zip_body": "ለመነሻውም ለመድረሻውም የፖስታ ኮድ ያስገቡ።", "create_shipment.missing_zip_title": "የፖስታ ኮዶች ያስፈልጋሉ", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ለዚህ መላኪያ ምንም ዋጋ አልመለሰም።", "create_shipment.no_rates_title": "ምንም ዋጋ የለም", "create_shipment.non_delivery_abandon": "መተው", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "እንደ ጥቅል አስቀምጥ", "create_shipment.save_package_dialog_label": "ለወደፊት ድጋሚ ጥቅም ላይ ለማዋል ይህን ጥቅል ይሰይሙ:", "create_shipment.save_package_dialog_title": "ጥቅል አስቀምጥ", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ላቤል ወደ {path} ተቀምጧል", "create_shipment.saved_title": "ተቀምጧል", "create_shipment.signature_adult": "የአዋቂ ፊርማ (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "የሙከራ ሁነታ መዝገቦች ብቻ እየታዩ ነው። የምርት ሁነታ መዝገቦች ለብቻቸው ይቀመጣሉ።", "dashboard.spend_includes_pending_refunds": "ተመላሽ ገንዘብ የሚጠባበቅ {amount} ያካትታል", "dashboard.title": "

ዳሽቦርድ

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "የተመላሽ ገንዘብ ሁኔታ ያረጋግጡ", "history.check_status_failed": "ሁኔታን ማረጋገጥ አልተቻለም:\n{error}", "history.column_carrier": "አጓጓዥ", @@ -404,6 +409,7 @@ "history.column_tracking_code": "የመከታተያ ቁጥር", "history.confirm_insure_purchase": "ለዚህ መላኪያ የ{amount} የመድን ሽፋን ግዛ።", "history.confirm_refund_request": "ለዚህ መላኪያ ላቤል ተመላሽ ገንዘብ ጠይቅ።", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ስህተት", "history.export_none_selected": "መጀመሪያ የተገዛ መለያ ያለው አንድ ወይም ከዚያ በላይ ጭነት ይምረጡ።", @@ -432,6 +438,10 @@ "history.table_group_title": "የተገዙ መላኪያዎች (በዚህ ሁነታ)", "history.title": "የመላኪያ ታሪክ", "history.update_insurance_button": "መድን አድስ", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "መግለጫ", "hts_lookup.col_general_rate": "አጠቃላይ ዋጋ", "hts_lookup.col_htsno": "የHTS ቁጥር", diff --git a/app/resources/locales/ar.json b/app/resources/locales/ar.json index 5d509a5..6b5ff97 100644 --- a/app/resources/locales/ar.json +++ b/app/resources/locales/ar.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "الحصول على الأسعار", "create_shipment.get_rates_error_body": "تعذر الحصول على الأسعار:\n{error}", "create_shipment.height_label": "الارتفاع ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "التأمين على القيمة:", "create_shipment.insurance_none": "بدون", "create_shipment.insurance_tooltip": "اختياري. يُرجى تحديد قيمة لتأمين الطرد عليها؛ تُحتسب التغطية عند شراء الملصق.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "اختر الجهة التي ستُرسل إليها الطرد في حقل «إلى».", "create_shipment.missing_zip_body": "أدخل رمزًا بريديًا لكل من المصدر والوجهة.", "create_shipment.missing_zip_title": "الرموز البريدية مطلوبة", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "لم يُرجع EasyPost أي أسعار لهذه الشحنة.", "create_shipment.no_rates_title": "لا توجد أسعار", "create_shipment.non_delivery_abandon": "التخلي عن الشحنة", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "حفظ كطرد", "create_shipment.save_package_dialog_label": "سمِّ هذا الطرد لإعادة استخدامه لاحقاً:", "create_shipment.save_package_dialog_title": "حفظ الطرد", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "تم حفظ الملصق في {path}", "create_shipment.saved_title": "تم الحفظ", "create_shipment.signature_adult": "توقيع شخص بالغ (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "يتم عرض سجلات وضع الاختبار فقط. تُحفظ سجلات وضع الإنتاج بشكل منفصل.", "dashboard.spend_includes_pending_refunds": "يشمل {amount} بانتظار الاسترداد", "dashboard.title": "

لوحة التحكم

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "التحقق من حالة الاسترداد", "history.check_status_failed": "تعذر التحقق من الحالة:\n{error}", "history.column_carrier": "شركة الشحن", @@ -404,6 +409,7 @@ "history.column_tracking_code": "رقم التتبع", "history.confirm_insure_purchase": "شراء تغطية تأمينية بقيمة {amount} لهذه الشحنة.", "history.confirm_refund_request": "طلب استرداد أموال ملصق هذه الشحنة.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "خطأ", "history.export_none_selected": "حدد أولاً شحنة واحدة أو أكثر تحتوي على ملصق تم شراؤه.", @@ -432,6 +438,10 @@ "history.table_group_title": "الشحنات المشتراة (هذا الوضع)", "history.title": "سجل الشحنات", "history.update_insurance_button": "تحديث التأمين", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "الوصف", "hts_lookup.col_general_rate": "السعر العام", "hts_lookup.col_htsno": "رقم HTS", diff --git a/app/resources/locales/bn.json b/app/resources/locales/bn.json index 60e3abf..b1066f7 100644 --- a/app/resources/locales/bn.json +++ b/app/resources/locales/bn.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "রেট পান", "create_shipment.get_rates_error_body": "রেট পাওয়া যায়নি:\n{error}", "create_shipment.height_label": "উচ্চতা ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "মূল্যের জন্য বিমা:", "create_shipment.insurance_none": "কোনওটিই নয়", "create_shipment.insurance_tooltip": "ঐচ্ছিক। পার্সেলটি যে মূল্যে বিমা করা হবে তা ঘোষণা করুন; লেবেল কেনার সময় কভারের জন্য চার্জ নেওয়া হয়।", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«প্রাপক» ঘরে পার্সেলটি কার কাছে যাবে তা বেছে নিন।", "create_shipment.missing_zip_body": "উৎস ও গন্তব্য উভয়ের জন্য একটি পোস্টাল কোড লিখুন।", "create_shipment.missing_zip_title": "পোস্টাল কোড প্রয়োজন", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "এই শিপমেন্টের জন্য EasyPost কোনো রেট ফেরত দেয়নি।", "create_shipment.no_rates_title": "কোনো রেট নেই", "create_shipment.non_delivery_abandon": "পরিত্যাগ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "প্যাকেজ হিসেবে সংরক্ষণ করুন", "create_shipment.save_package_dialog_label": "পরে পুনরায় ব্যবহারের জন্য এই প্যাকেজটির নাম দিন:", "create_shipment.save_package_dialog_title": "প্যাকেজ সংরক্ষণ করুন", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "লেবেল {path}-এ সংরক্ষিত হয়েছে", "create_shipment.saved_title": "সংরক্ষিত", "create_shipment.signature_adult": "প্রাপ্তবয়স্ক স্বাক্ষর (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "শুধুমাত্র টেস্ট মোডের রেকর্ড দেখানো হচ্ছে। প্রোডাকশন মোডের রেকর্ড আলাদাভাবে রাখা হয়।", "dashboard.spend_includes_pending_refunds": "রিফান্ডের অপেক্ষায় থাকা {amount} অন্তর্ভুক্ত", "dashboard.title": "

ড্যাশবোর্ড

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "রিফান্ডের অবস্থা যাচাই করুন", "history.check_status_failed": "অবস্থা যাচাই করা যায়নি:\n{error}", "history.column_carrier": "ক্যারিয়ার", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ট্র্যাকিং কোড", "history.confirm_insure_purchase": "এই শিপমেন্টের জন্য {amount} পরিমাণ বীমা কভারেজ কিনুন।", "history.confirm_refund_request": "এই শিপমেন্টের লেবেলের জন্য রিফান্ডের অনুরোধ করুন।", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ত্রুটি", "history.export_none_selected": "প্রথমে কেনা লেবেল সহ এক বা একাধিক চালান নির্বাচন করুন।", @@ -432,6 +438,10 @@ "history.table_group_title": "কেনা শিপমেন্ট (এই মোডে)", "history.title": "শিপমেন্ট ইতিহাস", "history.update_insurance_button": "বীমা হালনাগাদ করুন", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "বিবরণ", "hts_lookup.col_general_rate": "সাধারণ হার", "hts_lookup.col_htsno": "HTS নম্বর", diff --git a/app/resources/locales/cs.json b/app/resources/locales/cs.json index c0ffd6d..6734c9a 100644 --- a/app/resources/locales/cs.json +++ b/app/resources/locales/cs.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Získat sazby", "create_shipment.get_rates_error_body": "Sazby se nepodařilo získat:\n{error}", "create_shipment.height_label": "V ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Pojistit na hodnotu:", "create_shipment.insurance_none": "Žádná", "create_shipment.insurance_tooltip": "Volitelné. Uveďte hodnotu, na kterou má být zásilka pojištěna; pojištění se účtuje při nákupu štítku.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "V poli Komu vyberte, komu je zásilka určena.", "create_shipment.missing_zip_body": "Zadejte PSČ odesílatele i příjemce.", "create_shipment.missing_zip_title": "Je vyžadováno PSČ", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost nevrátil pro tuto zásilku žádné sazby.", "create_shipment.no_rates_title": "Žádné sazby", "create_shipment.non_delivery_abandon": "Vzdát se zásilky", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Uložit jako balík", "create_shipment.save_package_dialog_label": "Pojmenujte tento balík pro pozdější použití:", "create_shipment.save_package_dialog_title": "Uložit balík", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Štítek uložen do {path}", "create_shipment.saved_title": "Uloženo", "create_shipment.signature_adult": "Podpis dospělé osoby (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Zobrazují se pouze záznamy z testovacího režimu. Záznamy z produkčního režimu jsou vedeny odděleně.", "dashboard.spend_includes_pending_refunds": "Včetně {amount} čekajících na vrácení", "dashboard.title": "

Přehled

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Zkontrolovat stav vrácení peněz", "history.check_status_failed": "Stav se nepodařilo zkontrolovat:\n{error}", "history.column_carrier": "Dopravce", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Sledovací číslo", "history.confirm_insure_purchase": "Zakoupit pojištění ve výši {amount} pro tuto zásilku.", "history.confirm_refund_request": "Požádat o vrácení peněz za štítek této zásilky.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Chyba", "history.export_none_selected": "Nejprve vyberte jednu nebo více zásilek se zakoupeným štítkem.", @@ -432,6 +438,10 @@ "history.table_group_title": "Zakoupené zásilky (tento režim)", "history.title": "Historie zásilek", "history.update_insurance_button": "Aktualizovat pojištění", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Popis", "hts_lookup.col_general_rate": "Obecná sazba", "hts_lookup.col_htsno": "Číslo HTS", diff --git a/app/resources/locales/de.json b/app/resources/locales/de.json index d29e29c..e306281 100644 --- a/app/resources/locales/de.json +++ b/app/resources/locales/de.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Tarife abrufen", "create_shipment.get_rates_error_body": "Tarife konnten nicht abgerufen werden:\n{error}", "create_shipment.height_label": "H ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Wert versichern:", "create_shipment.insurance_none": "Keine", "create_shipment.insurance_tooltip": "Optional. Einen Wert angeben, für den das Paket versichert werden soll; die Deckung wird beim Kauf des Etiketts berechnet.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Wählen Sie unter „An“, an wen das Paket geht.", "create_shipment.missing_zip_body": "Geben Sie eine Postleitzahl für Absender und Empfänger ein.", "create_shipment.missing_zip_title": "Postleitzahlen erforderlich", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost hat keine Tarife für diese Sendung zurückgegeben.", "create_shipment.no_rates_title": "Keine Tarife", "create_shipment.non_delivery_abandon": "Aufgeben", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Als Paket speichern", "create_shipment.save_package_dialog_label": "Benennen Sie dieses Paket zur späteren Wiederverwendung:", "create_shipment.save_package_dialog_title": "Paket speichern", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etikett gespeichert unter {path}", "create_shipment.saved_title": "Gespeichert", "create_shipment.signature_adult": "Unterschrift eines Erwachsenen (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Es werden nur Einträge aus dem Testmodus angezeigt. Einträge aus dem Produktivmodus werden getrennt geführt.", "dashboard.spend_includes_pending_refunds": "Davon {amount} mit ausstehender Rückerstattung", "dashboard.title": "

Übersicht

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Rückerstattungsstatus prüfen", "history.check_status_failed": "Status konnte nicht geprüft werden:\n{error}", "history.column_carrier": "Versanddienstleister", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Sendungsnummer", "history.confirm_insure_purchase": "Versicherungsschutz in Höhe von {amount} für diese Sendung abschließen.", "history.confirm_refund_request": "Eine Rückerstattung für das Etikett dieser Sendung beantragen.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Fehler", "history.export_none_selected": "Wählen Sie zuerst eine oder mehrere Sendungen mit gekauftem Etikett aus.", @@ -432,6 +438,10 @@ "history.table_group_title": "Gekaufte Sendungen (dieser Modus)", "history.title": "Sendungsverlauf", "history.update_insurance_button": "Versicherung aktualisieren", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Beschreibung", "hts_lookup.col_general_rate": "Allgemeiner Satz", "hts_lookup.col_htsno": "HTS-Nummer", diff --git a/app/resources/locales/el.json b/app/resources/locales/el.json index f41cc4e..8b26428 100644 --- a/app/resources/locales/el.json +++ b/app/resources/locales/el.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Λήψη Τιμών", "create_shipment.get_rates_error_body": "Δεν ήταν δυνατή η λήψη τιμών:\n{error}", "create_shipment.height_label": "Υ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Ασφάλιση για αξία:", "create_shipment.insurance_none": "Καμία", "create_shipment.insurance_tooltip": "Προαιρετικό. Δηλώστε μια αξία για την ασφάλιση του δέματος· η κάλυψη χρεώνεται κατά την αγορά της ετικέτας.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Επιλέξτε στο πεδίο «Προς» σε ποιον πηγαίνει το δέμα.", "create_shipment.missing_zip_body": "Εισαγάγετε ταχυδρομικό κώδικα για την προέλευση και τον προορισμό.", "create_shipment.missing_zip_title": "Απαιτούνται ταχυδρομικοί κώδικες", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "Το EasyPost δεν επέστρεψε τιμές για αυτή την αποστολή.", "create_shipment.no_rates_title": "Καμία τιμή", "create_shipment.non_delivery_abandon": "Εγκατάλειψη", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Αποθήκευση ως δέμα", "create_shipment.save_package_dialog_label": "Ονομάστε αυτό το δέμα για μελλοντική χρήση:", "create_shipment.save_package_dialog_title": "Αποθήκευση δέματος", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Η ετικέτα αποθηκεύτηκε στο {path}", "create_shipment.saved_title": "Αποθηκεύτηκε", "create_shipment.signature_adult": "Υπογραφή ενήλικα (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Εμφανίζονται μόνο εγγραφές της λειτουργίας δοκιμής. Οι εγγραφές της λειτουργίας παραγωγής διατηρούνται χωριστά.", "dashboard.spend_includes_pending_refunds": "Περιλαμβάνει {amount} σε αναμονή επιστροφής", "dashboard.title": "

Πίνακας Ελέγχου

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Έλεγχος κατάστασης επιστροφής χρημάτων", "history.check_status_failed": "Δεν ήταν δυνατός ο έλεγχος της κατάστασης:\n{error}", "history.column_carrier": "Μεταφορέας", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Κωδικός παρακολούθησης", "history.confirm_insure_purchase": "Αγορά ασφαλιστικής κάλυψης {amount} για αυτή την αποστολή.", "history.confirm_refund_request": "Αίτημα επιστροφής χρημάτων για την ετικέτα αυτής της αποστολής.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Σφάλμα", "history.export_none_selected": "Επιλέξτε πρώτα μία ή περισσότερες αποστολές με αγορασμένη ετικέτα.", @@ -432,6 +438,10 @@ "history.table_group_title": "Αγορασμένες αποστολές (αυτή η λειτουργία)", "history.title": "Ιστορικό Αποστολών", "history.update_insurance_button": "Ενημέρωση ασφάλισης", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Περιγραφή", "hts_lookup.col_general_rate": "Γενικός Δασμός", "hts_lookup.col_htsno": "Αριθμός HTS", diff --git a/app/resources/locales/en.json b/app/resources/locales/en.json index b2010da..23f7552 100644 --- a/app/resources/locales/en.json +++ b/app/resources/locales/en.json @@ -303,6 +303,7 @@ "create_shipment.insurance_label": "Insure for value:", "create_shipment.insurance_none": "None", "create_shipment.insurance_tooltip": "Optional. Declare a value to insure the parcel for; the cover is charged when you buy the label.", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insured_note": "Insured for {amount}", "create_shipment.label_file_filter": "{format} files (*.{ext})", "create_shipment.length_label": "L ({unit}):", @@ -317,6 +318,7 @@ "create_shipment.missing_zip_title": "Postal codes required", "create_shipment.no_rates_body": "EasyPost returned no rates for this shipment.", "create_shipment.no_rates_title": "No rates", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.non_delivery_abandon": "Abandon", "create_shipment.non_delivery_label": "If undeliverable:", "create_shipment.non_delivery_return": "Return to sender", @@ -345,6 +347,7 @@ "create_shipment.result_group": "Purchased label", "create_shipment.same_address_body": "From and To are the same address. Choose a different recipient.", "create_shipment.same_address_title": "Same address", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.save_label_button": "Save label…", "create_shipment.save_label_dialog_title": "Save label", "create_shipment.save_label_error_body": "Could not save label:\n{error}", @@ -432,6 +435,13 @@ "history.table_group_title": "Purchased shipments (this mode)", "history.title": "Shipment History", "history.update_insurance_button": "Update insurance", + "history.void_order_button": "Void order", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", + "history.void_failed": "Could not void order:\n{error}", + "history.void_complete_title": "Order voided", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "hts_lookup.col_description": "Description", "hts_lookup.col_general_rate": "General Rate", "hts_lookup.col_htsno": "HTS Number", diff --git a/app/resources/locales/es.json b/app/resources/locales/es.json index 37863fa..96789a0 100644 --- a/app/resources/locales/es.json +++ b/app/resources/locales/es.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Obtener tarifas", "create_shipment.get_rates_error_body": "No se pudieron obtener las tarifas:\n{error}", "create_shipment.height_label": "Al ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Asegurar por valor:", "create_shipment.insurance_none": "Ninguno", "create_shipment.insurance_tooltip": "Opcional. Declare un valor por el que asegurar el paquete; la cobertura se cobra al comprar la etiqueta.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Elige en «Para» a quién va el paquete.", "create_shipment.missing_zip_body": "Introduzca un código postal para el origen y el destino.", "create_shipment.missing_zip_title": "Se requieren códigos postales", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost no devolvió tarifas para este envío.", "create_shipment.no_rates_title": "Sin tarifas", "create_shipment.non_delivery_abandon": "Abandonar", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Guardar como paquete", "create_shipment.save_package_dialog_label": "Asigna un nombre a este paquete para reutilizarlo más adelante:", "create_shipment.save_package_dialog_title": "Guardar paquete", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etiqueta guardada en {path}", "create_shipment.saved_title": "Guardado", "create_shipment.signature_adult": "Firma de adulto (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Solo se muestran los registros del modo prueba. Los registros del modo producción se guardan por separado.", "dashboard.spend_includes_pending_refunds": "Incluye {amount} pendiente de reembolso", "dashboard.title": "

Panel

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Consultar estado del reembolso", "history.check_status_failed": "No se pudo consultar el estado:\n{error}", "history.column_carrier": "Transportista", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Número de seguimiento", "history.confirm_insure_purchase": "Comprar cobertura de seguro de {amount} para este envío.", "history.confirm_refund_request": "Solicitar un reembolso para la etiqueta de este envío.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Error", "history.export_none_selected": "Seleccione primero uno o más envíos con una etiqueta comprada.", @@ -432,6 +438,10 @@ "history.table_group_title": "Envíos comprados (este modo)", "history.title": "Historial de envíos", "history.update_insurance_button": "Actualizar seguro", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Descripción", "hts_lookup.col_general_rate": "Tarifa general", "hts_lookup.col_htsno": "Número HTS", diff --git a/app/resources/locales/fa.json b/app/resources/locales/fa.json index bec61a2..6fa480c 100644 --- a/app/resources/locales/fa.json +++ b/app/resources/locales/fa.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "دریافت نرخ‌ها", "create_shipment.get_rates_error_body": "دریافت نرخ‌ها ممکن نشد:\n{error}", "create_shipment.height_label": "ارتفاع ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "بیمه برای ارزش:", "create_shipment.insurance_none": "هیچ‌کدام", "create_shipment.insurance_tooltip": "اختیاری. برای بیمه بسته مبلغی را اعلام کنید؛ هزینه پوشش هنگام خرید برچسب دریافت می‌شود.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "در بخش «به» مشخص کنید بسته برای چه کسی ارسال می‌شود.", "create_shipment.missing_zip_body": "برای مبدأ و مقصد کد پستی وارد کنید.", "create_shipment.missing_zip_title": "کد پستی لازم است", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost هیچ نرخی برای این مرسوله بازنگرداند.", "create_shipment.no_rates_title": "نرخی موجود نیست", "create_shipment.non_delivery_abandon": "رهاسازی", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "ذخیره به‌عنوان بسته", "create_shipment.save_package_dialog_label": "این بسته را برای استفاده مجدد در آینده نام‌گذاری کنید:", "create_shipment.save_package_dialog_title": "ذخیره بسته", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "برچسب در {path} ذخیره شد", "create_shipment.saved_title": "ذخیره شد", "create_shipment.signature_adult": "امضای بزرگسال (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "فقط سوابق حالت آزمایشی نمایش داده می‌شود. سوابق حالت تولید جداگانه نگهداری می‌شوند.", "dashboard.spend_includes_pending_refunds": "شامل {amount} در انتظار بازپرداخت", "dashboard.title": "

داشبورد

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "بررسی وضعیت بازپرداخت", "history.check_status_failed": "بررسی وضعیت ممکن نشد:\n{error}", "history.column_carrier": "شرکت حمل‌ونقل", @@ -404,6 +409,7 @@ "history.column_tracking_code": "کد رهگیری", "history.confirm_insure_purchase": "خرید پوشش بیمه‌ای به مبلغ {amount} برای این مرسوله.", "history.confirm_refund_request": "درخواست بازپرداخت برای برچسب این مرسوله.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "خطا", "history.export_none_selected": "ابتدا یک یا چند محموله با برچسب خریداری‌شده انتخاب کنید.", @@ -432,6 +438,10 @@ "history.table_group_title": "مرسولات خریداری‌شده (این حالت)", "history.title": "تاریخچه مرسولات", "history.update_insurance_button": "به‌روزرسانی بیمه", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "توضیحات", "hts_lookup.col_general_rate": "نرخ عمومی", "hts_lookup.col_htsno": "شماره HTS", diff --git a/app/resources/locales/fr.json b/app/resources/locales/fr.json index c1c5c57..ac672ad 100644 --- a/app/resources/locales/fr.json +++ b/app/resources/locales/fr.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Obtenir les tarifs", "create_shipment.get_rates_error_body": "Impossible d'obtenir les tarifs :\n{error}", "create_shipment.height_label": "H ({unit}) :", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Assurer pour la valeur :", "create_shipment.insurance_none": "Aucune", "create_shipment.insurance_tooltip": "Facultatif. Déclarer une valeur à assurer pour le colis ; la couverture est facturée à l'achat de l'étiquette.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Choisissez dans « Destinataire » à qui le colis est envoyé.", "create_shipment.missing_zip_body": "Saisissez un code postal pour l'origine et pour la destination.", "create_shipment.missing_zip_title": "Codes postaux requis", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost n'a renvoyé aucun tarif pour cette expédition.", "create_shipment.no_rates_title": "Aucun tarif", "create_shipment.non_delivery_abandon": "Abandon", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Enregistrer comme colis", "create_shipment.save_package_dialog_label": "Nommez ce colis pour le réutiliser plus tard :", "create_shipment.save_package_dialog_title": "Enregistrer le colis", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Étiquette enregistrée dans {path}", "create_shipment.saved_title": "Enregistré", "create_shipment.signature_adult": "Signature adulte (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Seuls les enregistrements du mode test sont affichés. Les enregistrements du mode production sont conservés séparément.", "dashboard.spend_includes_pending_refunds": "Dont {amount} en attente de remboursement", "dashboard.title": "

Tableau de bord

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Vérifier le statut du remboursement", "history.check_status_failed": "Impossible de vérifier le statut :\n{error}", "history.column_carrier": "Transporteur", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Numéro de suivi", "history.confirm_insure_purchase": "Souscrire une couverture d'assurance de {amount} pour cette expédition.", "history.confirm_refund_request": "Demander un remboursement pour l'étiquette de cette expédition.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Erreur", "history.export_none_selected": "Sélectionnez d'abord un ou plusieurs envois avec une étiquette achetée.", @@ -432,6 +438,10 @@ "history.table_group_title": "Expéditions achetées (ce mode)", "history.title": "Historique des expéditions", "history.update_insurance_button": "Mettre à jour l'assurance", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Description", "hts_lookup.col_general_rate": "Tarif général", "hts_lookup.col_htsno": "Numéro HTS", diff --git a/app/resources/locales/gu.json b/app/resources/locales/gu.json index 82294f7..c71ba0f 100644 --- a/app/resources/locales/gu.json +++ b/app/resources/locales/gu.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "દરો મેળવો", "create_shipment.get_rates_error_body": "દરો મેળવી શકાયા નહીં:\n{error}", "create_shipment.height_label": "ઊ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "મૂલ્ય માટે વીમો:", "create_shipment.insurance_none": "કોઈ નહીં", "create_shipment.insurance_tooltip": "વૈકલ્પિક. પાર્સલનો વીમો ઉતારવા માટે મૂલ્ય જાહેર કરો; લેબલ ખરીદતી વખતે કવરનો ચાર્જ લેવાય છે.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«પ્રતિ»માં પાર્સલ કોને મોકલવાનું છે તે પસંદ કરો.", "create_shipment.missing_zip_body": "મૂળ અને ગંતવ્ય બંને માટે પિન કોડ દાખલ કરો.", "create_shipment.missing_zip_title": "પિન કોડ જરૂરી છે", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost એ આ શિપમેન્ટ માટે કોઈ દર પરત કર્યા નથી.", "create_shipment.no_rates_title": "કોઈ દર નથી", "create_shipment.non_delivery_abandon": "ત્યજી દો", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "પેકેજ તરીકે સાચવો", "create_shipment.save_package_dialog_label": "પછીથી ફરીથી ઉપયોગ કરવા માટે આ પેકેજને નામ આપો:", "create_shipment.save_package_dialog_title": "પેકેજ સાચવો", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "લેબલ {path} પર સાચવાયું", "create_shipment.saved_title": "સાચવાયું", "create_shipment.signature_adult": "પુખ્ત સહી (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "ફક્ત ટેસ્ટ મોડના રેકોર્ડ બતાવવામાં આવી રહ્યા છે. પ્રોડક્શન મોડના રેકોર્ડ અલગ રાખવામાં આવે છે.", "dashboard.spend_includes_pending_refunds": "રિફંડની રાહ જોતા {amount} સહિત", "dashboard.title": "

ડેશબોર્ડ

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "રિફંડ સ્થિતિ તપાસો", "history.check_status_failed": "સ્થિતિ તપાસી શકાઈ નહીં:\n{error}", "history.column_carrier": "કેરિયર", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ટ્રેકિંગ કોડ", "history.confirm_insure_purchase": "આ શિપમેન્ટ માટે {amount} નું વીમા કવરેજ ખરીદો.", "history.confirm_refund_request": "આ શિપમેન્ટના લેબલ માટે રિફંડની વિનંતી કરો.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ભૂલ", "history.export_none_selected": "પહેલાં ખરીદેલ લેબલ સાથેની એક કે વધુ શિપમેન્ટ પસંદ કરો.", @@ -432,6 +438,10 @@ "history.table_group_title": "ખરીદેલ શિપમેન્ટ (આ મોડ)", "history.title": "શિપમેન્ટ ઇતિહાસ", "history.update_insurance_button": "વીમો અપડેટ કરો", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "વર્ણન", "hts_lookup.col_general_rate": "સામાન્ય દર", "hts_lookup.col_htsno": "HTS નંબર", diff --git a/app/resources/locales/ha.json b/app/resources/locales/ha.json index 6ee152e..ee9a843 100644 --- a/app/resources/locales/ha.json +++ b/app/resources/locales/ha.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Samo Farashi", "create_shipment.get_rates_error_body": "Ba a iya samo farashi ba:\n{error}", "create_shipment.height_label": "T ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Yi inshora don kima:", "create_shipment.insurance_none": "Babu", "create_shipment.insurance_tooltip": "Na zaɓi. Bayyana kima don yin inshorar fakiti; ana cajin kariya lokacin sayan lakabin.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Zaɓi a cikin «Zuwa» wanda za a aika wa kunshin.", "create_shipment.missing_zip_body": "Shigar da lambar gidan waya don wurin tashi da wurin zuwa.", "create_shipment.missing_zip_title": "Ana buƙatar lambar gidan waya", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost bai bayar da wani farashi ba don wannan kunshin.", "create_shipment.no_rates_title": "Babu Farashi", "create_shipment.non_delivery_abandon": "Watsar", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Ajiye a matsayin kunshin", "create_shipment.save_package_dialog_label": "Sanya wa wannan kunshin suna don sake amfani da shi daga baya:", "create_shipment.save_package_dialog_title": "Ajiye kunshin", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "An ajiye lambar aikawa zuwa {path}", "create_shipment.saved_title": "An Ajiye", "create_shipment.signature_adult": "Sa hannun manya (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Ana nuna bayanan yanayin gwaji kawai. Ana ajiye bayanan yanayin aiki na gaskiya daban.", "dashboard.spend_includes_pending_refunds": "Ya haɗa da {amount} da ke jiran mayar da kuɗi", "dashboard.title": "

Allon Bayanai

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Duba matsayin mayar da kudi", "history.check_status_failed": "Ba a iya duba matsayi ba:\n{error}", "history.column_carrier": "Kamfanin Jigilar Kaya", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Lambar bibiya", "history.confirm_insure_purchase": "Saya inshorar {amount} don wannan kunshin.", "history.confirm_refund_request": "Nemi mayar da kudin lambar aikawar wannan kunshin.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Kuskure", "history.export_none_selected": "Da farko zaɓi kaya ɗaya ko fiye da ke da lakabin da aka saya.", @@ -432,6 +438,10 @@ "history.table_group_title": "Kayan aikawa da aka saya (wannan yanayin)", "history.title": "Tarihin Aikawa", "history.update_insurance_button": "Sabunta inshora", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Bayani", "hts_lookup.col_general_rate": "Kudin Fito na Gaba Ɗaya", "hts_lookup.col_htsno": "Lambar HTS", diff --git a/app/resources/locales/he.json b/app/resources/locales/he.json index 9af8e49..d357eaf 100644 --- a/app/resources/locales/he.json +++ b/app/resources/locales/he.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "קבל תעריפים", "create_shipment.get_rates_error_body": "לא ניתן היה לקבל תעריפים:\n{error}", "create_shipment.height_label": "ג ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ביטוח לפי ערך:", "create_shipment.insurance_none": "ללא", "create_shipment.insurance_tooltip": "אופציונלי. יש להצהיר על ערך לביטוח החבילה; העלות נגבית בעת רכישת התווית.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "בחרו בשדה „אל” למי החבילה נשלחת.", "create_shipment.missing_zip_body": "הזן מיקוד עבור המוצא והיעד.", "create_shipment.missing_zip_title": "נדרשים מיקודים", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost לא החזירה תעריפים עבור משלוח זה.", "create_shipment.no_rates_title": "אין תעריפים", "create_shipment.non_delivery_abandon": "נטישה", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "שמור כחבילה", "create_shipment.save_package_dialog_label": "תן שם לחבילה זו לשימוש חוזר בעתיד:", "create_shipment.save_package_dialog_title": "שמירת חבילה", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "התווית נשמרה בנתיב {path}", "create_shipment.saved_title": "נשמר", "create_shipment.signature_adult": "חתימת מבוגר (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "מוצגות רשומות ממצב בדיקה בלבד. רשומות ממצב ייצור נשמרות בנפרד.", "dashboard.spend_includes_pending_refunds": "כולל {amount} שממתינים להחזר", "dashboard.title": "

לוח בקרה

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "בדוק סטטוס החזר כספי", "history.check_status_failed": "לא ניתן היה לבדוק את הסטטוס:\n{error}", "history.column_carrier": "חברת שילוח", @@ -404,6 +409,7 @@ "history.column_tracking_code": "מספר מעקב", "history.confirm_insure_purchase": "רכישת כיסוי ביטוחי בסך {amount} עבור משלוח זה.", "history.confirm_refund_request": "בקשת החזר כספי עבור תווית המשלוח הזו.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "שגיאה", "history.export_none_selected": "בחר תחילה משלוח אחד או יותר עם מדבקה שנרכשה.", @@ -432,6 +438,10 @@ "history.table_group_title": "משלוחים שנרכשו (במצב זה)", "history.title": "היסטוריית משלוחים", "history.update_insurance_button": "עדכן ביטוח", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "תיאור", "hts_lookup.col_general_rate": "תעריף כללי", "hts_lookup.col_htsno": "מספר HTS", diff --git a/app/resources/locales/hi.json b/app/resources/locales/hi.json index 62608d1..28734f9 100644 --- a/app/resources/locales/hi.json +++ b/app/resources/locales/hi.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "दरें प्राप्त करें", "create_shipment.get_rates_error_body": "दरें प्राप्त नहीं की जा सकीं:\n{error}", "create_shipment.height_label": "ऊं ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "मूल्य के लिए बीमा:", "create_shipment.insurance_none": "कोई नहीं", "create_shipment.insurance_tooltip": "वैकल्पिक। पार्सल का बीमा कराने के लिए मूल्य घोषित करें; लेबल खरीदते समय कवर का शुल्क लिया जाता है।", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«प्राप्तकर्ता» में चुनें कि पार्सल किसे भेजा जा रहा है।", "create_shipment.missing_zip_body": "प्रेषक और प्राप्तकर्ता दोनों के लिए पिन कोड दर्ज करें।", "create_shipment.missing_zip_title": "पिन कोड आवश्यक हैं", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "इस शिपमेंट के लिए EasyPost ने कोई दर नहीं लौटाई।", "create_shipment.no_rates_title": "कोई दर नहीं", "create_shipment.non_delivery_abandon": "त्याग दें", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "पैकेज के रूप में सहेजें", "create_shipment.save_package_dialog_label": "बाद में पुनः उपयोग के लिए इस पैकेज को नाम दें:", "create_shipment.save_package_dialog_title": "पैकेज सहेजें", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "लेबल {path} में सहेजा गया", "create_shipment.saved_title": "सहेजा गया", "create_shipment.signature_adult": "वयस्क हस्ताक्षर (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "केवल टेस्ट मोड के रिकॉर्ड दिखाए जा रहे हैं। प्रोडक्शन मोड के रिकॉर्ड अलग रखे जाते हैं।", "dashboard.spend_includes_pending_refunds": "रिफंड की प्रतीक्षा में {amount} शामिल", "dashboard.title": "

डैशबोर्ड

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "रिफंड स्थिति जांचें", "history.check_status_failed": "स्थिति जांची नहीं जा सकी:\n{error}", "history.column_carrier": "कैरियर", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ट्रैकिंग कोड", "history.confirm_insure_purchase": "इस शिपमेंट के लिए {amount} का बीमा कवरेज खरीदें।", "history.confirm_refund_request": "इस शिपमेंट के लेबल के लिए रिफंड का अनुरोध करें।", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "त्रुटि", "history.export_none_selected": "पहले खरीदे गए लेबल वाले एक या अधिक शिपमेंट चुनें।", @@ -432,6 +438,10 @@ "history.table_group_title": "खरीदे गए शिपमेंट (इस मोड में)", "history.title": "शिपमेंट इतिहास", "history.update_insurance_button": "बीमा अपडेट करें", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "विवरण", "hts_lookup.col_general_rate": "सामान्य दर", "hts_lookup.col_htsno": "HTS नंबर", diff --git a/app/resources/locales/hr.json b/app/resources/locales/hr.json index 3d292a1..aff14c0 100644 --- a/app/resources/locales/hr.json +++ b/app/resources/locales/hr.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Dohvati cijene", "create_shipment.get_rates_error_body": "Cijene nije moguće dohvatiti:\n{error}", "create_shipment.height_label": "V ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Osiguraj za vrijednost:", "create_shipment.insurance_none": "Nema", "create_shipment.insurance_tooltip": "Neobavezno. Prijavite vrijednost za osiguranje paketa; pokriće se naplaćuje pri kupnji naljepnice.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "U polju Za odaberite kome ide paket.", "create_shipment.missing_zip_body": "Unesite poštanski broj za polazište i za odredište.", "create_shipment.missing_zip_title": "Potrebni su poštanski brojevi", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost nije vratio nijednu cijenu za ovu pošiljku.", "create_shipment.no_rates_title": "Nema cijena", "create_shipment.non_delivery_abandon": "Napusti", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Spremi kao paket", "create_shipment.save_package_dialog_label": "Imenujte ovaj paket za buduću upotrebu:", "create_shipment.save_package_dialog_title": "Spremi paket", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Naljepnica spremljena na {path}", "create_shipment.saved_title": "Spremljeno", "create_shipment.signature_adult": "Potpis odrasle osobe (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Prikazuju se samo zapisi iz testnog načina rada. Zapisi iz proizvodnog načina rada vode se odvojeno.", "dashboard.spend_includes_pending_refunds": "Uključuje {amount} koji čeka povrat", "dashboard.title": "

Nadzorna ploča

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Provjeri status povrata", "history.check_status_failed": "Status nije moguće provjeriti:\n{error}", "history.column_carrier": "Dostavljač", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Broj za praćenje", "history.confirm_insure_purchase": "Kupi osiguranje u iznosu od {amount} za ovu pošiljku.", "history.confirm_refund_request": "Zatraži povrat za naljepnicu ove pošiljke.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Pogreška", "history.export_none_selected": "Najprije odaberite jednu ili više pošiljki s kupljenom naljepnicom.", @@ -432,6 +438,10 @@ "history.table_group_title": "Kupljene pošiljke (ovaj način rada)", "history.title": "Povijest pošiljaka", "history.update_insurance_button": "Ažuriraj osiguranje", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Opis", "hts_lookup.col_general_rate": "Opća stopa", "hts_lookup.col_htsno": "HTS broj", diff --git a/app/resources/locales/hu.json b/app/resources/locales/hu.json index e60faf2..b986242 100644 --- a/app/resources/locales/hu.json +++ b/app/resources/locales/hu.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Díjak lekérése", "create_shipment.get_rates_error_body": "Nem sikerült lekérni a díjakat:\n{error}", "create_shipment.height_label": "M ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Biztosítás értékre:", "create_shipment.insurance_none": "Nincs", "create_shipment.insurance_tooltip": "Választható. Adja meg a csomag biztosítási értékét; a fedezet a címke megvásárlásakor kerül felszámításra.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "A Címzett mezőben válassza ki, kinek szól a csomag.", "create_shipment.missing_zip_body": "Adjon meg irányítószámot a feladóhoz és a címzetthez is.", "create_shipment.missing_zip_title": "Irányítószám szükséges", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "Az EasyPost nem adott vissza díjakat ehhez a szállítmányhoz.", "create_shipment.no_rates_title": "Nincs elérhető díj", "create_shipment.non_delivery_abandon": "Elhagyás", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Mentés csomagként", "create_shipment.save_package_dialog_label": "Nevezze el ezt a csomagot a későbbi újrafelhasználáshoz:", "create_shipment.save_package_dialog_title": "Csomag mentése", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "A címke mentve ide: {path}", "create_shipment.saved_title": "Mentve", "create_shipment.signature_adult": "Felnőtt aláírása (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Csak a teszt üzemmód bejegyzései jelennek meg. Az éles üzemmód bejegyzéseit az alkalmazás külön tárolja.", "dashboard.spend_includes_pending_refunds": "Ebből {amount} visszatérítésre vár", "dashboard.title": "

Irányítópult

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Visszatérítés állapotának ellenőrzése", "history.check_status_failed": "Nem sikerült ellenőrizni az állapotot:\n{error}", "history.column_carrier": "Szállító", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Nyomkövetési szám", "history.confirm_insure_purchase": "{amount} összegű biztosítási fedezet vásárlása ehhez a szállítmányhoz.", "history.confirm_refund_request": "Visszatérítés igénylése ennek a szállítmánynak a címkéjére.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Hiba", "history.export_none_selected": "Először válasszon ki egy vagy több küldeményt megvásárolt címkével.", @@ -432,6 +438,10 @@ "history.table_group_title": "Megvásárolt szállítmányok (ebben a módban)", "history.title": "Szállítmány előzmények", "history.update_insurance_button": "Biztosítás frissítése", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Leírás", "hts_lookup.col_general_rate": "Általános vámtétel", "hts_lookup.col_htsno": "HTS-szám", diff --git a/app/resources/locales/id.json b/app/resources/locales/id.json index 4925ceb..f73519a 100644 --- a/app/resources/locales/id.json +++ b/app/resources/locales/id.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Dapatkan Tarif", "create_shipment.get_rates_error_body": "Tidak dapat mengambil tarif:\n{error}", "create_shipment.height_label": "T ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Asuransikan senilai:", "create_shipment.insurance_none": "Tidak ada", "create_shipment.insurance_tooltip": "Opsional. Nyatakan nilai untuk mengasuransikan paket; premi dikenakan saat membeli label.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Pilih di Kepada, untuk siapa paket ini dikirim.", "create_shipment.missing_zip_body": "Masukkan kode pos untuk asal dan tujuan.", "create_shipment.missing_zip_title": "Kode pos diperlukan", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost tidak mengembalikan tarif untuk pengiriman ini.", "create_shipment.no_rates_title": "Tidak ada tarif", "create_shipment.non_delivery_abandon": "Musnahkan", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Simpan sebagai paket", "create_shipment.save_package_dialog_label": "Beri nama paket ini untuk digunakan kembali nanti:", "create_shipment.save_package_dialog_title": "Simpan paket", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Label disimpan ke {path}", "create_shipment.saved_title": "Tersimpan", "create_shipment.signature_adult": "Tanda tangan dewasa (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Hanya menampilkan catatan mode uji. Catatan mode produksi disimpan secara terpisah.", "dashboard.spend_includes_pending_refunds": "Termasuk {amount} yang menunggu pengembalian dana", "dashboard.title": "

Dasbor

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Periksa status pengembalian dana", "history.check_status_failed": "Tidak dapat memeriksa status:\n{error}", "history.column_carrier": "Kurir", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Nomor resi", "history.confirm_insure_purchase": "Beli asuransi senilai {amount} untuk pengiriman ini.", "history.confirm_refund_request": "Ajukan pengembalian dana untuk label pengiriman ini.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Kesalahan", "history.export_none_selected": "Pilih satu atau beberapa kiriman dengan label yang sudah dibeli terlebih dahulu.", @@ -432,6 +438,10 @@ "history.table_group_title": "Pengiriman yang dibeli (mode ini)", "history.title": "Riwayat Pengiriman", "history.update_insurance_button": "Perbarui asuransi", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Deskripsi", "hts_lookup.col_general_rate": "Tarif Umum", "hts_lookup.col_htsno": "Nomor HTS", diff --git a/app/resources/locales/ig.json b/app/resources/locales/ig.json index 79417c9..7e31d8e 100644 --- a/app/resources/locales/ig.json +++ b/app/resources/locales/ig.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Nweta Ọnụahịa", "create_shipment.get_rates_error_body": "Enweghị ike nweta ọnụahịa:\n{error}", "create_shipment.height_label": "Ịdị elu ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Mkpuchi maka uru:", "create_shipment.insurance_none": "Ọ dịghị", "create_shipment.insurance_tooltip": "Nhọrọ. Kwupụta uru iji mkpuchi ngwugwu ahụ; a na-akwụ ụgwọ mkpuchi mgbe ị zụtara akara.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Họrọ na «Nye» onye a ga-ezigara ngwongwo a.", "create_shipment.missing_zip_body": "Tinye koodu nzipu ozi maka ebe mmalite na ebe njedebe.", "create_shipment.missing_zip_title": "Achọrọ koodu nzipu ozi", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost enyeghị ọnụahịa ọ bụla maka ngwongwo a.", "create_shipment.no_rates_title": "Enweghị ọnụahịa", "create_shipment.non_delivery_abandon": "Hapụ ya", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Chekwaa dị ka ngwongwo", "create_shipment.save_package_dialog_label": "Kpọọ ngwongwo a aha maka iji ya ọzọ n'ọdịnihu:", "create_shipment.save_package_dialog_title": "Chekwaa ngwongwo", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Echekwara akara na {path}", "create_shipment.saved_title": "Echekwara", "create_shipment.signature_adult": "Mbinye aka okenye (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Na-egosi naanị ndekọ ọnọdụ nnwale. A na-edebe ndekọ ọnọdụ mmepụta iche.", "dashboard.spend_includes_pending_refunds": "Gụnyere {amount} na-echere mbughachi ego", "dashboard.title": "

Bọọdụ Nchịkọta

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Lelee ọnọdụ ụgwọ mbughachi", "history.check_status_failed": "Enweghị ike ịlele ọnọdụ:\n{error}", "history.column_carrier": "Kompanị mbunye", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Koodu nchọpụta", "history.confirm_insure_purchase": "Zụta mkpuchi ihe mberede nke {amount} maka ngwongwo a.", "history.confirm_refund_request": "Rịọ ụgwọ mbughachi maka akara ngwongwo a.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Njehie", "history.export_none_selected": "Buru ụzọ họrọ otu mbupu ma ọ bụ karịa nwere leblu azụrụ azụ.", @@ -432,6 +438,10 @@ "history.table_group_title": "Ngwongwo azụtara (ọnọdụ a)", "history.title": "Akụkọ Ngwongwo", "history.update_insurance_button": "Melite mkpuchi", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Nkọwa", "hts_lookup.col_general_rate": "Ọnụahịa Izugbe", "hts_lookup.col_htsno": "Nọmba HTS", diff --git a/app/resources/locales/it.json b/app/resources/locales/it.json index c95c819..37439eb 100644 --- a/app/resources/locales/it.json +++ b/app/resources/locales/it.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Ottieni Tariffe", "create_shipment.get_rates_error_body": "Impossibile ottenere le tariffe:\n{error}", "create_shipment.height_label": "Alt. ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Assicura per valore:", "create_shipment.insurance_none": "Nessuno", "create_shipment.insurance_tooltip": "Facoltativo. Dichiara un valore per assicurare il pacco; la copertura viene addebitata all'acquisto dell'etichetta.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Scegli in «A» a chi è destinato il pacco.", "create_shipment.missing_zip_body": "Inserire un codice postale sia per l'origine sia per la destinazione.", "create_shipment.missing_zip_title": "Codici postali obbligatori", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost non ha restituito tariffe per questa spedizione.", "create_shipment.no_rates_title": "Nessuna tariffa", "create_shipment.non_delivery_abandon": "Abbandona", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Salva come pacco", "create_shipment.save_package_dialog_label": "Assegna un nome a questo pacco per riutilizzarlo in seguito:", "create_shipment.save_package_dialog_title": "Salva pacco", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etichetta salvata in {path}", "create_shipment.saved_title": "Salvato", "create_shipment.signature_adult": "Firma di adulto (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Vengono mostrati solo i record della modalità test. I record della modalità produzione sono conservati separatamente.", "dashboard.spend_includes_pending_refunds": "Di cui {amount} in attesa di rimborso", "dashboard.title": "

Dashboard

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Verifica stato rimborso", "history.check_status_failed": "Impossibile verificare lo stato:\n{error}", "history.column_carrier": "Corriere", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Numero di tracciamento", "history.confirm_insure_purchase": "Acquista una copertura assicurativa di {amount} per questa spedizione.", "history.confirm_refund_request": "Richiedi un rimborso per l'etichetta di questa spedizione.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Errore", "history.export_none_selected": "Seleziona prima una o più spedizioni con un'etichetta acquistata.", @@ -432,6 +438,10 @@ "history.table_group_title": "Spedizioni acquistate (questa modalità)", "history.title": "Cronologia Spedizioni", "history.update_insurance_button": "Aggiorna assicurazione", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Descrizione", "hts_lookup.col_general_rate": "Aliquota Generale", "hts_lookup.col_htsno": "Numero HTS", diff --git a/app/resources/locales/ja.json b/app/resources/locales/ja.json index 80982cc..a770bc9 100644 --- a/app/resources/locales/ja.json +++ b/app/resources/locales/ja.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "料金を取得", "create_shipment.get_rates_error_body": "料金を取得できませんでした:\n{error}", "create_shipment.height_label": "高さ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "補償金額:", "create_shipment.insurance_none": "なし", "create_shipment.insurance_tooltip": "任意。荷物に付ける補償額を申告します。補償料はラベル購入時に請求されます。", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "「宛先」で荷物の送り先を選択してください。", "create_shipment.missing_zip_body": "発送元と発送先の両方の郵便番号を入力してください。", "create_shipment.missing_zip_title": "郵便番号が必要です", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPostからこの配送の料金が返されませんでした。", "create_shipment.no_rates_title": "料金なし", "create_shipment.non_delivery_abandon": "放棄", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "パッケージとして保存", "create_shipment.save_package_dialog_label": "後で再利用するため、このパッケージに名前を付けてください:", "create_shipment.save_package_dialog_title": "パッケージを保存", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ラベルを{path}に保存しました", "create_shipment.saved_title": "保存済み", "create_shipment.signature_adult": "成人の署名(18歳以上)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "テストモードの記録のみを表示しています。本番モードの記録は別に保管されます。", "dashboard.spend_includes_pending_refunds": "うち {amount} は返金待ち", "dashboard.title": "

ダッシュボード

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "返金状況を確認", "history.check_status_failed": "状況を確認できませんでした:\n{error}", "history.column_carrier": "配送業者", @@ -404,6 +409,7 @@ "history.column_tracking_code": "追跡番号", "history.confirm_insure_purchase": "この配送に対して{amount}の保険を購入します。", "history.confirm_refund_request": "この配送のラベルについて返金を請求します。", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "エラー", "history.export_none_selected": "ラベルを購入済みの発送を1件以上選択してください。", @@ -432,6 +438,10 @@ "history.table_group_title": "購入済みの配送(このモード)", "history.title": "配送履歴", "history.update_insurance_button": "保険を更新", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "説明", "hts_lookup.col_general_rate": "一般税率", "hts_lookup.col_htsno": "HTS番号", diff --git a/app/resources/locales/jv.json b/app/resources/locales/jv.json index 6617012..c2113f4 100644 --- a/app/resources/locales/jv.json +++ b/app/resources/locales/jv.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Jaluk Tarif", "create_shipment.get_rates_error_body": "Ora bisa njaluk tarif:\n{error}", "create_shipment.height_label": "Dhuwur ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Asuransi kanggo regané:", "create_shipment.insurance_none": "Ora ana", "create_shipment.insurance_tooltip": "Opsional. Sebutna regané kanggo ngasuransi paket; premi ditarik nalika tuku label.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Pilih ing Marang, paket iki arep dikirim menyang sapa.", "create_shipment.missing_zip_body": "Lebokna kode pos kanggo asal lan tujuan.", "create_shipment.missing_zip_title": "Kode pos dibutuhake", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ora mbalekake tarif kanggo kiriman iki.", "create_shipment.no_rates_title": "Ora ana tarif", "create_shipment.non_delivery_abandon": "Ditinggal", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Simpen dadi paket", "create_shipment.save_package_dialog_label": "Wenehi jeneng paket iki kanggo digunakake maneh mengko:", "create_shipment.save_package_dialog_title": "Simpen paket", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Label disimpen menyang {path}", "create_shipment.saved_title": "Disimpen", "create_shipment.signature_adult": "Tapak asma diwasa (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Mung nuduhake cathetan mode uji. Cathetan mode produksi disimpen kapisah.", "dashboard.spend_includes_pending_refunds": "Kalebu {amount} sing ngenteni refund", "dashboard.title": "

Dasbor

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Priksa status refund", "history.check_status_failed": "Ora bisa mriksa status:\n{error}", "history.column_carrier": "Kurir", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Kode lacak", "history.confirm_insure_purchase": "Tuku tanggungan asuransi {amount} kanggo kiriman iki.", "history.confirm_refund_request": "Njaluk refund kanggo label kiriman iki.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Kesalahan", "history.export_none_selected": "Pilih siji utawa luwih kiriman sing duwe label sing wis dituku dhisik.", @@ -432,6 +438,10 @@ "history.table_group_title": "Kiriman sing wis dituku (mode iki)", "history.title": "Riwayat Kiriman", "history.update_insurance_button": "Nganyari asuransi", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Katrangan", "hts_lookup.col_general_rate": "Tarif Umum", "hts_lookup.col_htsno": "Nomer HTS", diff --git a/app/resources/locales/kn.json b/app/resources/locales/kn.json index afeeb80..85349b5 100644 --- a/app/resources/locales/kn.json +++ b/app/resources/locales/kn.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ದರಗಳನ್ನು ಪಡೆಯಿರಿ", "create_shipment.get_rates_error_body": "ದರಗಳನ್ನು ಪಡೆಯಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ:\n{error}", "create_shipment.height_label": "ಎತ್ತರ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ಮೌಲ್ಯಕ್ಕೆ ವಿಮೆ:", "create_shipment.insurance_none": "ಯಾವುದೂ ಇಲ್ಲ", "create_shipment.insurance_tooltip": "ಐಚ್ಛಿಕ. ಪಾರ್ಸೆಲ್‌ಗೆ ವಿಮೆ ಮಾಡಲು ಮೌಲ್ಯ ಘೋಷಿಸಿ; ಲೇಬಲ್ ಖರೀದಿಸುವಾಗ ವಿಮಾ ಶುಲ್ಕ ವಿಧಿಸಲಾಗುತ್ತದೆ.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«ಗೆ» ಎಂಬಲ್ಲಿ ಪಾರ್ಸೆಲ್ ಯಾರಿಗೆ ಹೋಗುತ್ತಿದೆ ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ.", "create_shipment.missing_zip_body": "ಮೂಲ ಮತ್ತು ಗಮ್ಯ ಎರಡಕ್ಕೂ ಪಿನ್ ಕೋಡ್ ನಮೂದಿಸಿ.", "create_shipment.missing_zip_title": "ಪಿನ್ ಕೋಡ್ ಅಗತ್ಯವಿದೆ", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "ಈ ಶಿಪ್‌ಮೆಂಟ್‌ಗೆ EasyPost ಯಾವುದೇ ದರಗಳನ್ನು ಹಿಂತಿರುಗಿಸಲಿಲ್ಲ.", "create_shipment.no_rates_title": "ದರಗಳಿಲ್ಲ", "create_shipment.non_delivery_abandon": "ತ್ಯಜಿಸಿ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "ಪ್ಯಾಕೇಜ್ ಆಗಿ ಉಳಿಸಿ", "create_shipment.save_package_dialog_label": "ನಂತರ ಮರುಬಳಕೆಗಾಗಿ ಈ ಪ್ಯಾಕೇಜ್‌ಗೆ ಹೆಸರಿಡಿ:", "create_shipment.save_package_dialog_title": "ಪ್ಯಾಕೇಜ್ ಉಳಿಸಿ", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ಲೇಬಲ್ {path} ಗೆ ಉಳಿಸಲಾಗಿದೆ", "create_shipment.saved_title": "ಉಳಿಸಲಾಗಿದೆ", "create_shipment.signature_adult": "ವಯಸ್ಕರ ಸಹಿ (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "ಟೆಸ್ಟ್ ಮೋಡ್ ದಾಖಲೆಗಳನ್ನು ಮಾತ್ರ ತೋರಿಸಲಾಗುತ್ತಿದೆ. ಪ್ರೊಡಕ್ಷನ್ ಮೋಡ್ ದಾಖಲೆಗಳನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ಇರಿಸಲಾಗುತ್ತದೆ.", "dashboard.spend_includes_pending_refunds": "ಮರುಪಾವತಿಗಾಗಿ ಕಾಯುತ್ತಿರುವ {amount} ಸೇರಿದೆ", "dashboard.title": "

ಡ್ಯಾಶ್‌ಬೋರ್ಡ್

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "ಮರುಪಾವತಿ ಸ್ಥಿತಿ ಪರಿಶೀಲಿಸಿ", "history.check_status_failed": "ಸ್ಥಿತಿ ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ:\n{error}", "history.column_carrier": "ವಾಹಕ", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ಟ್ರ್ಯಾಕಿಂಗ್ ಕೋಡ್", "history.confirm_insure_purchase": "ಈ ಶಿಪ್‌ಮೆಂಟ್‌ಗೆ {amount} ವಿಮಾ ಕವರೇಜ್ ಖರೀದಿಸಿ.", "history.confirm_refund_request": "ಈ ಶಿಪ್‌ಮೆಂಟ್‌ನ ಲೇಬಲ್‌ಗಾಗಿ ಮರುಪಾವತಿಯನ್ನು ವಿನಂತಿಸಿ.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ದೋಷ", "history.export_none_selected": "ಮೊದಲು ಖರೀದಿಸಿದ ಲೇಬಲ್ ಹೊಂದಿರುವ ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಾಗಣೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ.", @@ -432,6 +438,10 @@ "history.table_group_title": "ಖರೀದಿಸಿದ ಶಿಪ್‌ಮೆಂಟ್‌ಗಳು (ಈ ಮೋಡ್)", "history.title": "ಶಿಪ್‌ಮೆಂಟ್ ಇತಿಹಾಸ", "history.update_insurance_button": "ವಿಮೆ ನವೀಕರಿಸಿ", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "ವಿವರಣೆ", "hts_lookup.col_general_rate": "ಸಾಮಾನ್ಯ ದರ", "hts_lookup.col_htsno": "HTS ಸಂಖ್ಯೆ", diff --git a/app/resources/locales/ko.json b/app/resources/locales/ko.json index 3a40bbc..373d3da 100644 --- a/app/resources/locales/ko.json +++ b/app/resources/locales/ko.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "요금 조회", "create_shipment.get_rates_error_body": "요금을 조회할 수 없습니다:\n{error}", "create_shipment.height_label": "높이 ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "보험 가액:", "create_shipment.insurance_none": "없음", "create_shipment.insurance_tooltip": "선택 사항. 소포에 보험을 적용할 가액을 신고하세요. 보상은 라벨 구매 시 청구됩니다.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "'받는 사람'에서 소포를 받을 사람을 선택하세요.", "create_shipment.missing_zip_body": "출발지와 도착지의 우편번호를 모두 입력하세요.", "create_shipment.missing_zip_title": "우편번호가 필요합니다", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost에서 이 배송 건에 대한 요금을 반환하지 않았습니다.", "create_shipment.no_rates_title": "요금 없음", "create_shipment.non_delivery_abandon": "폐기", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "패키지로 저장", "create_shipment.save_package_dialog_label": "나중에 재사용할 수 있도록 이 패키지의 이름을 지정하세요:", "create_shipment.save_package_dialog_title": "패키지 저장", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "운송장이 {path}에 저장되었습니다", "create_shipment.saved_title": "저장됨", "create_shipment.signature_adult": "성인 서명 (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "테스트 모드 기록만 표시합니다. 프로덕션 모드 기록은 별도로 보관됩니다.", "dashboard.spend_includes_pending_refunds": "환불 대기 중인 {amount} 포함", "dashboard.title": "

대시보드

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "환불 상태 확인", "history.check_status_failed": "상태를 확인할 수 없습니다:\n{error}", "history.column_carrier": "배송업체", @@ -404,6 +409,7 @@ "history.column_tracking_code": "운송장 번호", "history.confirm_insure_purchase": "이 배송 건에 대해 {amount} 보험을 구매합니다.", "history.confirm_refund_request": "이 배송 건 운송장의 환불을 요청합니다.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "오류", "history.export_none_selected": "라벨을 구매한 배송을 하나 이상 먼저 선택하세요.", @@ -432,6 +438,10 @@ "history.table_group_title": "구매한 배송 건(현재 모드)", "history.title": "배송 내역", "history.update_insurance_button": "보험 정보 업데이트", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "설명", "hts_lookup.col_general_rate": "일반 세율", "hts_lookup.col_htsno": "HTS 번호", diff --git a/app/resources/locales/ml.json b/app/resources/locales/ml.json index b4953c1..5c5649e 100644 --- a/app/resources/locales/ml.json +++ b/app/resources/locales/ml.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "നിരക്കുകൾ നേടുക", "create_shipment.get_rates_error_body": "നിരക്കുകൾ ലഭിക്കാൻ കഴിഞ്ഞില്ല:\n{error}", "create_shipment.height_label": "ഉയരം ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "മൂല്യത്തിന് ഇൻഷുർ ചെയ്യുക:", "create_shipment.insurance_none": "ഒന്നുമില്ല", "create_shipment.insurance_tooltip": "ഓപ്ഷണൽ. പാഴ്സൽ ഇൻഷുർ ചെയ്യാൻ ഒരു മൂല്യം പ്രഖ്യാപിക്കുക; ലേബൽ വാങ്ങുമ്പോൾ പരിരക്ഷയ്ക്ക് നിരക്ക് ഈടാക്കും.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "പാഴ്സൽ ആർക്കാണ് അയക്കുന്നതെന്ന് «സ്വീകർത്താവ്» എന്നതിൽ തിരഞ്ഞെടുക്കുക.", "create_shipment.missing_zip_body": "ഉറവിടത്തിനും ലക്ഷ്യസ്ഥാനത്തിനും പിൻ കോഡ് നൽകുക.", "create_shipment.missing_zip_title": "പിൻ കോഡ് ആവശ്യമാണ്", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "ഈ ഷിപ്മെന്റിന് EasyPost ഒരു നിരക്കും തിരികെ നൽകിയില്ല.", "create_shipment.no_rates_title": "നിരക്കുകൾ ലഭ്യമല്ല", "create_shipment.non_delivery_abandon": "ഉപേക്ഷിക്കുക", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "പാക്കേജായി സംരക്ഷിക്കുക", "create_shipment.save_package_dialog_label": "പിന്നീട് വീണ്ടും ഉപയോഗിക്കാൻ ഈ പാക്കേജിന് പേര് നൽകുക:", "create_shipment.save_package_dialog_title": "പാക്കേജ് സംരക്ഷിക്കുക", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ലേബൽ {path} എന്നതിൽ സംരക്ഷിച്ചു", "create_shipment.saved_title": "സംരക്ഷിച്ചു", "create_shipment.signature_adult": "മുതിർന്നവരുടെ ഒപ്പ് (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "ടെസ്റ്റ് മോഡ് രേഖകൾ മാത്രമാണ് കാണിക്കുന്നത്. പ്രൊഡക്ഷൻ മോഡ് രേഖകൾ പ്രത്യേകമായി സൂക്ഷിക്കുന്നു.", "dashboard.spend_includes_pending_refunds": "റീഫണ്ടിനായി കാത്തിരിക്കുന്ന {amount} ഉൾപ്പെടെ", "dashboard.title": "

ഡാഷ്ബോർഡ്

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "റീഫണ്ട് നില പരിശോധിക്കുക", "history.check_status_failed": "നില പരിശോധിക്കാൻ കഴിഞ്ഞില്ല:\n{error}", "history.column_carrier": "കാരിയർ", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ട്രാക്കിംഗ് കോഡ്", "history.confirm_insure_purchase": "ഈ ഷിപ്മെന്റിന് {amount} തുകയുടെ ഇൻഷുറൻസ് കവറേജ് വാങ്ങുക.", "history.confirm_refund_request": "ഈ ഷിപ്മെന്റിന്റെ ലേബലിന് റീഫണ്ട് അഭ്യർത്ഥിക്കുക.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "പിശക്", "history.export_none_selected": "ആദ്യം വാങ്ങിയ ലേബലുള്ള ഒന്നോ അതിലധികമോ ഷിപ്‌മെന്റുകൾ തിരഞ്ഞെടുക്കുക.", @@ -432,6 +438,10 @@ "history.table_group_title": "വാങ്ങിയ ഷിപ്മെന്റുകൾ (ഈ മോഡ്)", "history.title": "ഷിപ്മെന്റ് ചരിത്രം", "history.update_insurance_button": "ഇൻഷുറൻസ് പുതുക്കുക", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "വിവരണം", "hts_lookup.col_general_rate": "പൊതു നിരക്ക്", "hts_lookup.col_htsno": "HTS നമ്പർ", diff --git a/app/resources/locales/mr.json b/app/resources/locales/mr.json index 65fda87..d634459 100644 --- a/app/resources/locales/mr.json +++ b/app/resources/locales/mr.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "दर मिळवा", "create_shipment.get_rates_error_body": "दर मिळवता आले नाहीत:\n{error}", "create_shipment.height_label": "उंची ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "मूल्यासाठी विमा:", "create_shipment.insurance_none": "काहीही नाही", "create_shipment.insurance_tooltip": "पर्यायी. पार्सलचा विमा उतरवण्यासाठी मूल्य जाहीर करा; लेबल खरेदी करताना संरक्षणासाठी शुल्क आकारले जाते.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«प्रति» मध्ये पार्सल कोणाला जात आहे ते निवडा.", "create_shipment.missing_zip_body": "स्रोत आणि गंतव्य दोन्हींसाठी पिन कोड प्रविष्ट करा.", "create_shipment.missing_zip_title": "पिन कोड आवश्यक", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ने या शिपमेंटसाठी कोणतेही दर परत केले नाहीत.", "create_shipment.no_rates_title": "दर उपलब्ध नाहीत", "create_shipment.non_delivery_abandon": "सोडून द्या", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "पॅकेज म्हणून जतन करा", "create_shipment.save_package_dialog_label": "नंतर पुन्हा वापरण्यासाठी या पॅकेजला नाव द्या:", "create_shipment.save_package_dialog_title": "पॅकेज जतन करा", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "लेबल {path} येथे जतन केले", "create_shipment.saved_title": "जतन केले", "create_shipment.signature_adult": "प्रौढ स्वाक्षरी (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "फक्त टेस्ट मोडचे रेकॉर्ड दाखवले जात आहेत. प्रॉडक्शन मोडचे रेकॉर्ड स्वतंत्रपणे ठेवले जातात.", "dashboard.spend_includes_pending_refunds": "परताव्याच्या प्रतीक्षेतील {amount} समाविष्ट", "dashboard.title": "

डॅशबोर्ड

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "परतावा स्थिती तपासा", "history.check_status_failed": "स्थिती तपासता आली नाही:\n{error}", "history.column_carrier": "कॅरियर", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ट्रॅकिंग कोड", "history.confirm_insure_purchase": "या शिपमेंटसाठी {amount} चे विमा संरक्षण खरेदी करा.", "history.confirm_refund_request": "या शिपमेंटच्या लेबलसाठी परतावा विनंती करा.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "त्रुटी", "history.export_none_selected": "प्रथम खरेदी केलेल्या लेबलसह एक किंवा अधिक शिपमेंट निवडा.", @@ -432,6 +438,10 @@ "history.table_group_title": "खरेदी केलेल्या शिपमेंट्स (हा मोड)", "history.title": "शिपमेंट इतिहास", "history.update_insurance_button": "विमा अद्यतनित करा", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "वर्णन", "hts_lookup.col_general_rate": "सामान्य दर", "hts_lookup.col_htsno": "HTS क्रमांक", diff --git a/app/resources/locales/ms.json b/app/resources/locales/ms.json index 87cb632..4ddc0cb 100644 --- a/app/resources/locales/ms.json +++ b/app/resources/locales/ms.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Dapatkan Kadar", "create_shipment.get_rates_error_body": "Tidak dapat mendapatkan kadar:\n{error}", "create_shipment.height_label": "T ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Insurans untuk nilai:", "create_shipment.insurance_none": "Tiada", "create_shipment.insurance_tooltip": "Pilihan. Isytiharkan nilai untuk menginsuranskan bungkusan; perlindungan dikenakan bayaran semasa membeli label.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Pilih dalam Kepada, siapa yang akan menerima bungkusan ini.", "create_shipment.missing_zip_body": "Masukkan poskod untuk kedua-dua asal dan destinasi.", "create_shipment.missing_zip_title": "Poskod diperlukan", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost tidak mengembalikan sebarang kadar untuk penghantaran ini.", "create_shipment.no_rates_title": "Tiada kadar", "create_shipment.non_delivery_abandon": "Lupuskan", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Simpan sebagai bungkusan", "create_shipment.save_package_dialog_label": "Namakan bungkusan ini untuk kegunaan semula kemudian:", "create_shipment.save_package_dialog_title": "Simpan bungkusan", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Label disimpan ke {path}", "create_shipment.saved_title": "Disimpan", "create_shipment.signature_adult": "Tandatangan dewasa (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Hanya memaparkan rekod mod ujian. Rekod mod pengeluaran disimpan secara berasingan.", "dashboard.spend_includes_pending_refunds": "Termasuk {amount} yang menunggu bayaran balik", "dashboard.title": "

Papan Pemuka

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Semak status bayaran balik", "history.check_status_failed": "Tidak dapat menyemak status:\n{error}", "history.column_carrier": "Syarikat Penghantaran", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Kod penjejakan", "history.confirm_insure_purchase": "Beli perlindungan insurans sebanyak {amount} untuk penghantaran ini.", "history.confirm_refund_request": "Mohon bayaran balik untuk label penghantaran ini.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Ralat", "history.export_none_selected": "Pilih satu atau lebih penghantaran dengan label yang telah dibeli dahulu.", @@ -432,6 +438,10 @@ "history.table_group_title": "Penghantaran dibeli (mod ini)", "history.title": "Sejarah Penghantaran", "history.update_insurance_button": "Kemas kini insurans", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Penerangan", "hts_lookup.col_general_rate": "Kadar Am", "hts_lookup.col_htsno": "Nombor HTS", diff --git a/app/resources/locales/my.json b/app/resources/locales/my.json index e56265d..a4f2011 100644 --- a/app/resources/locales/my.json +++ b/app/resources/locales/my.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "နှုန်းထားများ ရယူရန်", "create_shipment.get_rates_error_body": "နှုန်းထားများကို ရယူ၍ မရပါ:\n{error}", "create_shipment.height_label": "အမြင့် ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "တန်ဖိုးအတွက် အာမခံရန်:", "create_shipment.insurance_none": "မရှိ", "create_shipment.insurance_tooltip": "ရွေးချယ်နိုင်သည်။ ပါဆယ်ကို အာမခံရန် တန်ဖိုးတစ်ခု ကြေညာပါ။ လေဘယ်ဝယ်ယူချိန်တွင် အကာအကွယ်အတွက် ကြေးကောက်ခံပါမည်။", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "ပါဆယ်ကို မည်သူ့ထံ ပို့မည်ကို «ရရှိသူ» တွင် ရွေးပါ။", "create_shipment.missing_zip_body": "မူလနေရာနှင့် ဦးတည်ရာ နှစ်ခုစလုံးအတွက် စာတိုက်ကုဒ် ထည့်ပါ။", "create_shipment.missing_zip_title": "စာတိုက်ကုဒ် လိုအပ်သည်", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "ဤပို့ဆောင်မှုအတွက် EasyPost မှ နှုန်းထားများ ပြန်မပေးပါ။", "create_shipment.no_rates_title": "နှုန်းထားများ မရှိပါ", "create_shipment.non_delivery_abandon": "စွန့်ပစ်ရန်", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "ပါဆယ်အဖြစ် သိမ်းဆည်းရန်", "create_shipment.save_package_dialog_label": "နောင်တွင် ပြန်လည်အသုံးပြုရန် ဤပါဆယ်ကို အမည်ပေးပါ:", "create_shipment.save_package_dialog_title": "ပါဆယ်ကို သိမ်းဆည်းရန်", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "အညွှန်းကို {path} တွင် သိမ်းဆည်းပြီးပါပြီ", "create_shipment.saved_title": "သိမ်းဆည်းပြီးပါပြီ", "create_shipment.signature_adult": "အရွယ်ရောက်ပြီးသူ လက်မှတ် (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "စမ်းသပ်မုဒ် မှတ်တမ်းများကိုသာ ပြသထားသည်။ ထုတ်လုပ်မှုမုဒ် မှတ်တမ်းများကို သီးခြားသိမ်းဆည်းထားသည်။", "dashboard.spend_includes_pending_refunds": "ပြန်အမ်းငွေ စောင့်ဆိုင်းနေသော {amount} ပါဝင်သည်", "dashboard.title": "

ဒက်ရှ်ဘုတ်

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "ပြန်အမ်းငွေ အခြေအနေကို စစ်ဆေးရန်", "history.check_status_failed": "အခြေအနေကို စစ်ဆေး၍ မရပါ:\n{error}", "history.column_carrier": "သယ်ယူပို့ဆောင်သူ", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ခြေရာခံကုဒ်", "history.confirm_insure_purchase": "ဤပို့ဆောင်မှုအတွက် {amount} အာမခံလွှမ်းခြုံမှုကို ဝယ်ယူပါ။", "history.confirm_refund_request": "ဤပို့ဆောင်မှု၏ အညွှန်းအတွက် ပြန်အမ်းငွေကို တောင်းဆိုပါ။", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "အမှား", "history.export_none_selected": "ဝယ်ယူထားသော တံဆိပ်ပါသည့် ပို့ဆောင်မှု တစ်ခု သို့မဟုတ် ထို့ထက်ပိုကို ဦးစွာ ရွေးချယ်ပါ။", @@ -432,6 +438,10 @@ "history.table_group_title": "ဝယ်ယူထားသော ပို့ဆောင်မှုများ (ဤမုဒ်)", "history.title": "ပို့ဆောင်မှု မှတ်တမ်း", "history.update_insurance_button": "အာမခံကို ပြန်လည်မွမ်းမံရန်", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "ဖော်ပြချက်", "hts_lookup.col_general_rate": "အထွေထွေနှုန်း", "hts_lookup.col_htsno": "HTS နံပါတ်", diff --git a/app/resources/locales/ne.json b/app/resources/locales/ne.json index 763ad78..33d0869 100644 --- a/app/resources/locales/ne.json +++ b/app/resources/locales/ne.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "दरहरू प्राप्त गर्नुहोस्", "create_shipment.get_rates_error_body": "दरहरू प्राप्त गर्न सकिएन:\n{error}", "create_shipment.height_label": "उ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "मूल्यको लागि बिमा:", "create_shipment.insurance_none": "कुनै पनि होइन", "create_shipment.insurance_tooltip": "वैकल्पिक। पार्सल बिमा गर्न मूल्य घोषणा गर्नुहोस्; लेबल किन्दा कभरको शुल्क लाग्छ।", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«प्रति» मा पार्सल कसलाई जाँदै छ छान्नुहोस्।", "create_shipment.missing_zip_body": "स्रोत र गन्तव्य दुवैका लागि पोस्टल कोड प्रविष्ट गर्नुहोस्।", "create_shipment.missing_zip_title": "पोस्टल कोड आवश्यक", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "यस ढुवानीका लागि EasyPost ले कुनै दर फर्काएन।", "create_shipment.no_rates_title": "कुनै दर छैन", "create_shipment.non_delivery_abandon": "त्याग्नुहोस्", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "पार्सलको रूपमा सुरक्षित गर्नुहोस्", "create_shipment.save_package_dialog_label": "पछि पुन: प्रयोगका लागि यो पार्सललाई नाम दिनुहोस्:", "create_shipment.save_package_dialog_title": "पार्सल सुरक्षित गर्नुहोस्", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "लेबल {path} मा सुरक्षित गरियो", "create_shipment.saved_title": "सुरक्षित गरियो", "create_shipment.signature_adult": "वयस्क हस्ताक्षर (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "परीक्षण मोडका रेकर्डहरू मात्र देखाइँदैछ। उत्पादन मोडका रेकर्डहरू छुट्टै राखिन्छन्।", "dashboard.spend_includes_pending_refunds": "फिर्ता पर्खिरहेको {amount} समावेश", "dashboard.title": "

ड्यासबोर्ड

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "फिर्ता स्थिति जाँच गर्नुहोस्", "history.check_status_failed": "स्थिति जाँच गर्न सकिएन:\n{error}", "history.column_carrier": "ढुवानी कम्पनी", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ट्र्याकिङ कोड", "history.confirm_insure_purchase": "यस ढुवानीका लागि {amount} को बीमा कवरेज खरिद गर्नुहोस्।", "history.confirm_refund_request": "यस ढुवानीको लेबलका लागि फिर्ता अनुरोध गर्नुहोस्।", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "त्रुटि", "history.export_none_selected": "पहिले किनिएको लेबल भएको एक वा बढी ढुवानी चयन गर्नुहोस्।", @@ -432,6 +438,10 @@ "history.table_group_title": "खरिद गरिएका ढुवानीहरू (यो मोड)", "history.title": "ढुवानी इतिहास", "history.update_insurance_button": "बीमा अद्यावधिक गर्नुहोस्", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "विवरण", "hts_lookup.col_general_rate": "सामान्य दर", "hts_lookup.col_htsno": "HTS नम्बर", diff --git a/app/resources/locales/nl.json b/app/resources/locales/nl.json index df152ae..e22822d 100644 --- a/app/resources/locales/nl.json +++ b/app/resources/locales/nl.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Tarieven ophalen", "create_shipment.get_rates_error_body": "Kan tarieven niet ophalen:\n{error}", "create_shipment.height_label": "H ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Verzekeren voor waarde:", "create_shipment.insurance_none": "Geen", "create_shipment.insurance_tooltip": "Optioneel. Geef een waarde op om het pakket voor te verzekeren; de dekking wordt in rekening gebracht bij aankoop van het label.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Kies bij Aan naar wie het pakket gaat.", "create_shipment.missing_zip_body": "Voer een postcode in voor zowel de afzender als de ontvanger.", "create_shipment.missing_zip_title": "Postcodes vereist", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost heeft geen tarieven geretourneerd voor deze zending.", "create_shipment.no_rates_title": "Geen tarieven", "create_shipment.non_delivery_abandon": "Laten vervallen", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Opslaan als pakket", "create_shipment.save_package_dialog_label": "Geef dit pakket een naam voor later hergebruik:", "create_shipment.save_package_dialog_title": "Pakket opslaan", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Label opgeslagen op {path}", "create_shipment.saved_title": "Opgeslagen", "create_shipment.signature_adult": "Handtekening volwassene (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Alleen gegevens uit de testmodus worden getoond. Gegevens uit de productiemodus worden apart bewaard.", "dashboard.spend_includes_pending_refunds": "Waarvan {amount} wacht op terugbetaling", "dashboard.title": "

Dashboard

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Terugbetalingsstatus controleren", "history.check_status_failed": "Kan status niet controleren:\n{error}", "history.column_carrier": "Vervoerder", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Trackingcode", "history.confirm_insure_purchase": "Sluit een verzekering van {amount} af voor deze zending.", "history.confirm_refund_request": "Terugbetaling aanvragen voor het label van deze zending.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Fout", "history.export_none_selected": "Selecteer eerst een of meer zendingen met een gekocht label.", @@ -432,6 +438,10 @@ "history.table_group_title": "Gekochte zendingen (deze modus)", "history.title": "Verzendgeschiedenis", "history.update_insurance_button": "Verzekering bijwerken", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Omschrijving", "hts_lookup.col_general_rate": "Algemeen tarief", "hts_lookup.col_htsno": "HTS-nummer", diff --git a/app/resources/locales/or.json b/app/resources/locales/or.json index 4abf314..693a589 100644 --- a/app/resources/locales/or.json +++ b/app/resources/locales/or.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ଦର ପାଆନ୍ତୁ", "create_shipment.get_rates_error_body": "ଦର ପାଇପାରିଲା ନାହିଁ:\n{error}", "create_shipment.height_label": "ଉ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ମୂଲ୍ୟ ପାଇଁ ବୀମା:", "create_shipment.insurance_none": "କିଛି ନାହିଁ", "create_shipment.insurance_tooltip": "ବୈକଳ୍ପିକ। ପାର୍ସଲ ବୀମା କରିବା ପାଇଁ ଏକ ମୂଲ୍ୟ ଘୋଷଣା କରନ୍ତୁ; ଲେବଲ କିଣିବା ସମୟରେ କଭର ପାଇଁ ଚାର୍ଜ ଲାଗେ।", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«କୁ»ରେ ପାର୍ସଲ କାହା ପାଖକୁ ଯାଉଛି ବାଛନ୍ତୁ।", "create_shipment.missing_zip_body": "ଉତ୍ସ ଏବଂ ଗନ୍ତବ୍ୟ ଉଭୟ ପାଇଁ ପିନ୍ କୋଡ୍ ଦିଅନ୍ତୁ।", "create_shipment.missing_zip_title": "ପିନ୍ କୋଡ୍ ଆବଶ୍ୟକ", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "ଏହି ଶିପମେଣ୍ଟ ପାଇଁ EasyPost କୌଣସି ଦର ଫେରାଇଲା ନାହିଁ।", "create_shipment.no_rates_title": "କୌଣସି ଦର ନାହିଁ", "create_shipment.non_delivery_abandon": "ପରିତ୍ୟାଗ କରନ୍ତୁ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "ପାର୍ସେଲ୍ ଭାବେ ସେଭ୍ କରନ୍ତୁ", "create_shipment.save_package_dialog_label": "ପରେ ପୁନଃବ୍ୟବହାର ପାଇଁ ଏହି ପାର୍ସେଲ୍‌କୁ ନାମ ଦିଅନ୍ତୁ:", "create_shipment.save_package_dialog_title": "ପାର୍ସେଲ୍ ସେଭ୍ କରନ୍ତୁ", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ଲେବଲ୍ {path} ରେ ସେଭ୍ ହେଲା", "create_shipment.saved_title": "ସେଭ୍ ହେଲା", "create_shipment.signature_adult": "ବୟସ୍କ ସ୍ୱାକ୍ଷର (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "କେବଳ ଟେଷ୍ଟ ମୋଡ୍‌ର ରେକର୍ଡ ଦେଖାଯାଉଛି। ପ୍ରୋଡକ୍ସନ ମୋଡ୍‌ର ରେକର୍ଡ ଅଲଗା ରଖାଯାଏ।", "dashboard.spend_includes_pending_refunds": "ରିଫଣ୍ଡ ଅପେକ୍ଷାରେ ଥିବା {amount} ସାମିଲ", "dashboard.title": "

ଡ୍ୟାସବୋର୍ଡ

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "ରିଫଣ୍ଡ ସ୍ଥିତି ଯାଞ୍ଚ କରନ୍ତୁ", "history.check_status_failed": "ସ୍ଥିତି ଯାଞ୍ଚ କରିପାରିଲା ନାହିଁ:\n{error}", "history.column_carrier": "କେରିଅର୍", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ଟ୍ରାକିଂ କୋଡ୍", "history.confirm_insure_purchase": "ଏହି ଶିପମେଣ୍ଟ ପାଇଁ {amount} ର ବୀମା କଭରେଜ୍ କିଣନ୍ତୁ।", "history.confirm_refund_request": "ଏହି ଶିପମେଣ୍ଟର ଲେବଲ୍ ପାଇଁ ରିଫଣ୍ଡ ଅନୁରୋଧ କରନ୍ତୁ।", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ତ୍ରୁଟି", "history.export_none_selected": "ପ୍ରଥମେ କ୍ରୟ କରାଯାଇଥିବା ଲେବଲ୍ ଥିବା ଏକ କିମ୍ବା ଅଧିକ ଶିପମେଣ୍ଟ ମନୋନୀତ କରନ୍ତୁ।", @@ -432,6 +438,10 @@ "history.table_group_title": "କିଣା ଯାଇଥିବା ଶିପମେଣ୍ଟ (ଏହି ମୋଡ୍)", "history.title": "ଶିପମେଣ୍ଟ ଇତିହାସ", "history.update_insurance_button": "ବୀମା ଅପଡେଟ୍ କରନ୍ତୁ", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "ବର୍ଣ୍ଣନା", "hts_lookup.col_general_rate": "ସାଧାରଣ ଦର", "hts_lookup.col_htsno": "HTS ନମ୍ବର", diff --git a/app/resources/locales/pa.json b/app/resources/locales/pa.json index 91a2bee..4a8f653 100644 --- a/app/resources/locales/pa.json +++ b/app/resources/locales/pa.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ਰੇਟ ਲਵੋ", "create_shipment.get_rates_error_body": "ਰੇਟ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋ ਸਕੇ:\n{error}", "create_shipment.height_label": "ਉ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ਮੁੱਲ ਲਈ ਬੀਮਾ:", "create_shipment.insurance_none": "ਕੋਈ ਨਹੀਂ", "create_shipment.insurance_tooltip": "ਵਿਕਲਪਿਕ। ਪਾਰਸਲ ਦਾ ਬੀਮਾ ਕਰਨ ਲਈ ਇੱਕ ਮੁੱਲ ਐਲਾਨ ਕਰੋ; ਲੇਬਲ ਖਰੀਦਣ ਵੇਲੇ ਕਵਰ ਲਈ ਚਾਰਜ ਲਿਆ ਜਾਂਦਾ ਹੈ।", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«ਨੂੰ» ਵਿੱਚ ਚੁਣੋ ਕਿ ਪਾਰਸਲ ਕਿਸ ਨੂੰ ਜਾ ਰਿਹਾ ਹੈ।", "create_shipment.missing_zip_body": "ਸਰੋਤ ਅਤੇ ਮੰਜ਼ਿਲ ਦੋਹਾਂ ਲਈ ਪਿੰਨ ਕੋਡ ਦਰਜ ਕਰੋ।", "create_shipment.missing_zip_title": "ਪਿੰਨ ਕੋਡ ਲੋੜੀਂਦੇ ਹਨ", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ਨੇ ਇਸ ਸ਼ਿਪਮੈਂਟ ਲਈ ਕੋਈ ਰੇਟ ਵਾਪਸ ਨਹੀਂ ਭੇਜਿਆ।", "create_shipment.no_rates_title": "ਕੋਈ ਰੇਟ ਨਹੀਂ", "create_shipment.non_delivery_abandon": "ਛੱਡ ਦਿਓ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "ਪਾਰਸਲ ਵਜੋਂ ਸੰਭਾਲੋ", "create_shipment.save_package_dialog_label": "ਬਾਅਦ ਵਿੱਚ ਮੁੜ ਵਰਤੋਂ ਲਈ ਇਸ ਪਾਰਸਲ ਦਾ ਨਾਮ ਰੱਖੋ:", "create_shipment.save_package_dialog_title": "ਪਾਰਸਲ ਸੰਭਾਲੋ", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ਲੇਬਲ {path} ਵਿੱਚ ਸੰਭਾਲਿਆ ਗਿਆ", "create_shipment.saved_title": "ਸੰਭਾਲਿਆ ਗਿਆ", "create_shipment.signature_adult": "ਬਾਲਗ ਦਸਤਖਤ (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "ਸਿਰਫ਼ ਟੈਸਟ ਮੋਡ ਦੇ ਰਿਕਾਰਡ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ। ਉਤਪਾਦਨ ਮੋਡ ਦੇ ਰਿਕਾਰਡ ਵੱਖਰੇ ਰੱਖੇ ਜਾਂਦੇ ਹਨ।", "dashboard.spend_includes_pending_refunds": "ਰਿਫੰਡ ਦੀ ਉਡੀਕ ਵਿੱਚ {amount} ਸ਼ਾਮਲ", "dashboard.title": "

ਡੈਸ਼ਬੋਰਡ

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "ਰਿਫੰਡ ਸਥਿਤੀ ਜਾਂਚੋ", "history.check_status_failed": "ਸਥਿਤੀ ਜਾਂਚੀ ਨਹੀਂ ਜਾ ਸਕੀ:\n{error}", "history.column_carrier": "ਕੈਰੀਅਰ", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ਟਰੈਕਿੰਗ ਕੋਡ", "history.confirm_insure_purchase": "ਇਸ ਸ਼ਿਪਮੈਂਟ ਲਈ {amount} ਦਾ ਬੀਮਾ ਕਵਰੇਜ ਖਰੀਦੋ।", "history.confirm_refund_request": "ਇਸ ਸ਼ਿਪਮੈਂਟ ਦੇ ਲੇਬਲ ਲਈ ਰਿਫੰਡ ਦੀ ਬੇਨਤੀ ਕਰੋ।", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ਗਲਤੀ", "history.export_none_selected": "ਪਹਿਲਾਂ ਖਰੀਦੇ ਗਏ ਲੇਬਲ ਵਾਲੀਆਂ ਇੱਕ ਜਾਂ ਵੱਧ ਸ਼ਿਪਮੈਂਟਾਂ ਚੁਣੋ।", @@ -432,6 +438,10 @@ "history.table_group_title": "ਖਰੀਦੀਆਂ ਸ਼ਿਪਮੈਂਟਾਂ (ਇਹ ਮੋਡ)", "history.title": "ਸ਼ਿਪਮੈਂਟ ਇਤਿਹਾਸ", "history.update_insurance_button": "ਬੀਮਾ ਅੱਪਡੇਟ ਕਰੋ", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "ਵੇਰਵਾ", "hts_lookup.col_general_rate": "ਆਮ ਰੇਟ", "hts_lookup.col_htsno": "HTS ਨੰਬਰ", diff --git a/app/resources/locales/pl.json b/app/resources/locales/pl.json index 5e9097b..9b47770 100644 --- a/app/resources/locales/pl.json +++ b/app/resources/locales/pl.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Pobierz stawki", "create_shipment.get_rates_error_body": "Nie można pobrać stawek:\n{error}", "create_shipment.height_label": "W ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Ubezpiecz na kwotę:", "create_shipment.insurance_none": "Brak", "create_shipment.insurance_tooltip": "Opcjonalne. Zadeklaruj wartość, na jaką ma być ubezpieczona przesyłka; opłata za ochronę jest naliczana przy zakupie etykiety.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "W polu Do wybierz, do kogo trafi paczka.", "create_shipment.missing_zip_body": "Podaj kod pocztowy nadawcy i odbiorcy.", "create_shipment.missing_zip_title": "Wymagane kody pocztowe", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost nie zwrócił żadnych stawek dla tej przesyłki.", "create_shipment.no_rates_title": "Brak stawek", "create_shipment.non_delivery_abandon": "Porzucenie", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Zapisz jako paczkę", "create_shipment.save_package_dialog_label": "Nadaj nazwę tej paczce do późniejszego użycia:", "create_shipment.save_package_dialog_title": "Zapisz paczkę", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etykieta zapisana w {path}", "create_shipment.saved_title": "Zapisano", "create_shipment.signature_adult": "Podpis osoby dorosłej (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Wyświetlane są tylko rekordy z trybu testowego. Rekordy z trybu produkcyjnego są przechowywane oddzielnie.", "dashboard.spend_includes_pending_refunds": "W tym {amount} oczekuje na zwrot", "dashboard.title": "

Panel główny

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Sprawdź status zwrotu", "history.check_status_failed": "Nie można sprawdzić statusu:\n{error}", "history.column_carrier": "Przewoźnik", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Numer śledzenia", "history.confirm_insure_purchase": "Kup ochronę ubezpieczeniową w wysokości {amount} dla tej przesyłki.", "history.confirm_refund_request": "Poproś o zwrot za etykietę tej przesyłki.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Błąd", "history.export_none_selected": "Najpierw wybierz co najmniej jedną przesyłkę z zakupioną etykietą.", @@ -432,6 +438,10 @@ "history.table_group_title": "Zakupione przesyłki (ten tryb)", "history.title": "Historia przesyłek", "history.update_insurance_button": "Zaktualizuj ubezpieczenie", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Opis", "hts_lookup.col_general_rate": "Stawka ogólna", "hts_lookup.col_htsno": "Numer HTS", diff --git a/app/resources/locales/pt.json b/app/resources/locales/pt.json index 6a84603..744b871 100644 --- a/app/resources/locales/pt.json +++ b/app/resources/locales/pt.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Obter Tarifas", "create_shipment.get_rates_error_body": "Não foi possível obter as tarifas:\n{error}", "create_shipment.height_label": "A ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Segurar pelo valor:", "create_shipment.insurance_none": "Nenhum", "create_shipment.insurance_tooltip": "Opcional. Declare um valor para segurar a encomenda; a cobertura é cobrada na compra da etiqueta.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Escolha em Para a quem se destina a encomenda.", "create_shipment.missing_zip_body": "Introduza um código postal para a origem e para o destino.", "create_shipment.missing_zip_title": "Códigos postais obrigatórios", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "O EasyPost não retornou tarifas para este envio.", "create_shipment.no_rates_title": "Nenhuma tarifa", "create_shipment.non_delivery_abandon": "Abandonar", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Salvar como pacote", "create_shipment.save_package_dialog_label": "Nomeie este pacote para reutilizá-lo mais tarde:", "create_shipment.save_package_dialog_title": "Salvar pacote", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etiqueta salva em {path}", "create_shipment.saved_title": "Salvo", "create_shipment.signature_adult": "Assinatura de adulto (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Esta página mostra apenas dados do modo de teste. Os dados do modo de produção são mantidos à parte.", "dashboard.spend_includes_pending_refunds": "Inclui {amount} a aguardar reembolso", "dashboard.title": "

Painel

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Verificar status do reembolso", "history.check_status_failed": "Não foi possível verificar o status:\n{error}", "history.column_carrier": "Transportadora", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Código de rastreamento", "history.confirm_insure_purchase": "Comprar cobertura de seguro de {amount} para este envio.", "history.confirm_refund_request": "Solicitar reembolso da etiqueta deste envio.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Erro", "history.export_none_selected": "Selecione primeiro uma ou mais remessas com uma etiqueta comprada.", @@ -432,6 +438,10 @@ "history.table_group_title": "Envios comprados (este modo)", "history.title": "Histórico de Envios", "history.update_insurance_button": "Atualizar seguro", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Descrição", "hts_lookup.col_general_rate": "Tarifa Geral", "hts_lookup.col_htsno": "Número HTS", diff --git a/app/resources/locales/ro.json b/app/resources/locales/ro.json index 620122f..d87aa33 100644 --- a/app/resources/locales/ro.json +++ b/app/resources/locales/ro.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Obține tarife", "create_shipment.get_rates_error_body": "Tarifele nu au putut fi obținute:\n{error}", "create_shipment.height_label": "Î ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Asigură pentru valoarea:", "create_shipment.insurance_none": "Niciuna", "create_shipment.insurance_tooltip": "Opțional. Declară o valoare pentru asigurarea coletului; acoperirea se taxează la cumpărarea etichetei.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Alegeți la Către cui îi este trimis coletul.", "create_shipment.missing_zip_body": "Introduceți un cod poștal pentru origine și pentru destinație.", "create_shipment.missing_zip_title": "Coduri poștale necesare", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost nu a returnat niciun tarif pentru această expediere.", "create_shipment.no_rates_title": "Niciun tarif", "create_shipment.non_delivery_abandon": "Abandonează", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Salvează ca colet", "create_shipment.save_package_dialog_label": "Denumește acest colet pentru reutilizare ulterioară:", "create_shipment.save_package_dialog_title": "Salvează coletul", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etichetă salvată la {path}", "create_shipment.saved_title": "Salvat", "create_shipment.signature_adult": "Semnătură adult (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Se afișează doar înregistrările din modul test. Înregistrările din modul producție sunt păstrate separat.", "dashboard.spend_includes_pending_refunds": "Include {amount} în așteptarea rambursării", "dashboard.title": "

Panou de control

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Verifică starea rambursării", "history.check_status_failed": "Starea nu a putut fi verificată:\n{error}", "history.column_carrier": "Curier", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Cod de urmărire", "history.confirm_insure_purchase": "Achiziționează asigurare în valoare de {amount} pentru această expediere.", "history.confirm_refund_request": "Solicită o rambursare pentru eticheta acestei expedieri.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Eroare", "history.export_none_selected": "Selectați mai întâi una sau mai multe expedieri cu o etichetă achiziționată.", @@ -432,6 +438,10 @@ "history.table_group_title": "Expedieri achiziționate (acest mod)", "history.title": "Istoric expedieri", "history.update_insurance_button": "Actualizează asigurarea", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Descriere", "hts_lookup.col_general_rate": "Tarif general", "hts_lookup.col_htsno": "Număr HTS", diff --git a/app/resources/locales/ru.json b/app/resources/locales/ru.json index e0c7203..91ebb9a 100644 --- a/app/resources/locales/ru.json +++ b/app/resources/locales/ru.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Получить тарифы", "create_shipment.get_rates_error_body": "Не удалось получить тарифы:\n{error}", "create_shipment.height_label": "В ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Застраховать на сумму:", "create_shipment.insurance_none": "Нет", "create_shipment.insurance_tooltip": "Необязательно. Укажите сумму для страхования посылки; страховка оплачивается при покупке этикетки.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "В поле «Куда» выберите, кому отправляется посылка.", "create_shipment.missing_zip_body": "Введите почтовый индекс отправителя и получателя.", "create_shipment.missing_zip_title": "Требуются почтовые индексы", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost не вернул тарифы для этого отправления.", "create_shipment.no_rates_title": "Тарифы отсутствуют", "create_shipment.non_delivery_abandon": "Отказаться от отправления", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Сохранить как посылку", "create_shipment.save_package_dialog_label": "Назовите эту посылку для повторного использования:", "create_shipment.save_package_dialog_title": "Сохранение посылки", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Этикетка сохранена в {path}", "create_shipment.saved_title": "Сохранено", "create_shipment.signature_adult": "Подпись взрослого (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Показаны только записи тестового режима. Записи режима production хранятся отдельно.", "dashboard.spend_includes_pending_refunds": "В том числе {amount} ожидают возврата", "dashboard.title": "

Панель управления

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Проверить статус возврата", "history.check_status_failed": "Не удалось проверить статус:\n{error}", "history.column_carrier": "Перевозчик", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Номер отслеживания", "history.confirm_insure_purchase": "Оформить страховое покрытие на сумму {amount} для этого отправления.", "history.confirm_refund_request": "Запросить возврат средств за этикетку этого отправления.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Ошибка", "history.export_none_selected": "Сначала выберите одно или несколько отправлений с приобретённой этикеткой.", @@ -432,6 +438,10 @@ "history.table_group_title": "Купленные отправления (текущий режим)", "history.title": "История отправлений", "history.update_insurance_button": "Обновить страховку", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Описание", "hts_lookup.col_general_rate": "Обычная ставка", "hts_lookup.col_htsno": "Номер HTS", diff --git a/app/resources/locales/si.json b/app/resources/locales/si.json index 0ce6c71..aea8213 100644 --- a/app/resources/locales/si.json +++ b/app/resources/locales/si.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ගාස්තු ලබාගන්න", "create_shipment.get_rates_error_body": "ගාස්තු ලබාගත නොහැකි විය:\n{error}", "create_shipment.height_label": "උ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "වටිනාකමට රක්ෂණය:", "create_shipment.insurance_none": "කිසිවක් නැත", "create_shipment.insurance_tooltip": "විකල්ප. පාර්සලය රක්ෂණය කිරීමට වටිනාකමක් ප්‍රකාශ කරන්න; ලේබලය මිලදී ගැනීමේදී ආවරණය සඳහා ගාස්තු අය කෙරේ.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "පාර්සලය යවන්නේ කාටදැයි «වෙත» තුළ තෝරන්න.", "create_shipment.missing_zip_body": "ආරම්භය සහ ගමනාන්තය යන දෙකටම තැපැල් කේතයක් ඇතුළත් කරන්න.", "create_shipment.missing_zip_title": "තැපැල් කේත අවශ්‍යයි", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost විසින් මෙම එවුම සඳහා කිසිදු ගාස්තුවක් ලබා දුන්නේ නැත.", "create_shipment.no_rates_title": "ගාස්තු නොමැත", "create_shipment.non_delivery_abandon": "අත්හරින්න", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "පාර්සලයක් ලෙස සුරකින්න", "create_shipment.save_package_dialog_label": "පසුව නැවත භාවිතයට මෙම පාර්සලයට නමක් දෙන්න:", "create_shipment.save_package_dialog_title": "පාර්සලය සුරකින්න", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "ලේබලය {path} වෙත සුරකින ලදී", "create_shipment.saved_title": "සුරකින ලදී", "create_shipment.signature_adult": "වැඩිහිටි අත්සන (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "පරීක්ෂණ ප්‍රකාරයේ සටහන් පමණක් පෙන්වයි. නිෂ්පාදන ප්‍රකාරයේ සටහන් වෙනම තබා ඇත.", "dashboard.spend_includes_pending_refunds": "මුදල් ආපසු ගෙවීම බලාපොරොත්තුවෙන් සිටින {amount} ඇතුළත්", "dashboard.title": "

උපකරණ පුවරුව

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "මුදල් ආපසු ගෙවීමේ තත්ත්වය පරීක්ෂා කරන්න", "history.check_status_failed": "තත්ත්වය පරීක්ෂා කළ නොහැකි විය:\n{error}", "history.column_carrier": "භාරදෙන සමාගම", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ලුහුබැඳීමේ කේතය", "history.confirm_insure_purchase": "මෙම එවුම සඳහා {amount} ක රක්ෂණ ආවරණයක් මිලදී ගන්න.", "history.confirm_refund_request": "මෙම එවුමේ ලේබලය සඳහා මුදල් ආපසු ගෙවීමක් ඉල්ලන්න.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "දෝෂය", "history.export_none_selected": "පළමුව මිලදී ගත් ලේබලයක් සහිත නැව්ගත කිරීම් එකක් හෝ කිහිපයක් තෝරන්න.", @@ -432,6 +438,10 @@ "history.table_group_title": "මිලදී ගත් එවුම් (මෙම ප්‍රකාරය)", "history.title": "එවුම් ඉතිහාසය", "history.update_insurance_button": "රක්ෂණය යාවත්කාලීන කරන්න", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "විස්තරය", "hts_lookup.col_general_rate": "සාමාන්‍ය ගාස්තුව", "hts_lookup.col_htsno": "HTS අංකය", diff --git a/app/resources/locales/so.json b/app/resources/locales/so.json index 7d7838e..1369327 100644 --- a/app/resources/locales/so.json +++ b/app/resources/locales/so.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Hel Qiimaha", "create_shipment.get_rates_error_body": "Qiimaha lama helin karin:\n{error}", "create_shipment.height_label": "J ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Caymis qiimaha:", "create_shipment.insurance_none": "Midna", "create_shipment.insurance_tooltip": "Ikhtiyaari. Caddee qiimaha lagu caymiyo xirmada; kharashka waxaa la qaadaa marka la iibsanayo summada.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Ku dooro «Loo Diray» qofka xidhmada loo dirayo.", "create_shipment.missing_zip_body": "Geli lambar boostada meesha laga soo diray iyo meesha loo dirayba.", "create_shipment.missing_zip_title": "Lambarrada boostada waa loo baahan yahay", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ma soo celin qiimayaal shixnadkan.", "create_shipment.no_rates_title": "Qiimayaal Ma Jiraan", "create_shipment.non_delivery_abandon": "Ka tanaasul", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "U kaydi sida xirmo", "create_shipment.save_package_dialog_label": "U magacaw xirmadan si aad mar dambe u isticmaasho:", "create_shipment.save_package_dialog_title": "Kaydi xirmada", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Summadka waxaa lagu kaydiyay {path}", "create_shipment.saved_title": "La Kaydiyay", "create_shipment.signature_adult": "Saxeex qof qaangaar ah (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Waxaa la muujinayaa diiwaannada habka tijaabada oo keliya. Diiwaannada habka dhabta ah si gaar ah ayaa loo hayaa.", "dashboard.spend_includes_pending_refunds": "Waxaa ku jira {amount} sugaya lacag celin", "dashboard.title": "

Dashboard

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Hubi xaalada lacag celinta", "history.check_status_failed": "Xaalada lama hubin karin:\n{error}", "history.column_carrier": "Shirkadda Gaadiidka", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Koodhka Raadraaca", "history.confirm_insure_purchase": "Iibso daboolka caymiska ee {amount} shixnadkan.", "history.confirm_refund_request": "Codso lacag celin summadka shixnadkan.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Khalad", "history.export_none_selected": "Marka hore dooro hal ama in ka badan oo shixnado ah oo leh sumad la iibsaday.", @@ -432,6 +438,10 @@ "history.table_group_title": "Shixnadaha La Iibsaday (habkan)", "history.title": "Taariikhda Shixnadaha", "history.update_insurance_button": "Cusboonaysii Caymiska", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Sharaxaad", "hts_lookup.col_general_rate": "Qiimaha Guud", "hts_lookup.col_htsno": "Lambarka HTS", diff --git a/app/resources/locales/sv.json b/app/resources/locales/sv.json index f4a0076..10c799a 100644 --- a/app/resources/locales/sv.json +++ b/app/resources/locales/sv.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Hämta priser", "create_shipment.get_rates_error_body": "Kunde inte hämta priser:\n{error}", "create_shipment.height_label": "H ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Försäkra för värde:", "create_shipment.insurance_none": "Ingen", "create_shipment.insurance_tooltip": "Valfritt. Ange ett värde att försäkra paketet för; skyddet debiteras vid köp av fraktsedeln.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Välj under Till vem paketet ska till.", "create_shipment.missing_zip_body": "Ange postnummer för både avsändare och mottagare.", "create_shipment.missing_zip_title": "Postnummer krävs", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost returnerade inga priser för denna sändning.", "create_shipment.no_rates_title": "Inga priser", "create_shipment.non_delivery_abandon": "Överge", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Spara som paket", "create_shipment.save_package_dialog_label": "Namnge detta paket för senare återanvändning:", "create_shipment.save_package_dialog_title": "Spara paket", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Fraktsedeln sparades till {path}", "create_shipment.saved_title": "Sparad", "create_shipment.signature_adult": "Signatur av vuxen (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Visar endast poster från testläge. Poster från produktionsläge sparas separat.", "dashboard.spend_includes_pending_refunds": "Varav {amount} väntar på återbetalning", "dashboard.title": "

Översikt

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Kontrollera återbetalningsstatus", "history.check_status_failed": "Kunde inte kontrollera status:\n{error}", "history.column_carrier": "Transportör", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Spårningsnummer", "history.confirm_insure_purchase": "Köp försäkringsskydd på {amount} för denna sändning.", "history.confirm_refund_request": "Begär återbetalning för denna sändnings fraktsedel.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Fel", "history.export_none_selected": "Välj först en eller flera försändelser med en köpt etikett.", @@ -432,6 +438,10 @@ "history.table_group_title": "Köpta sändningar (detta läge)", "history.title": "Sändningshistorik", "history.update_insurance_button": "Uppdatera försäkring", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Beskrivning", "hts_lookup.col_general_rate": "Allmän tullsats", "hts_lookup.col_htsno": "HTS-nummer", diff --git a/app/resources/locales/sw.json b/app/resources/locales/sw.json index ab717b4..1cb673c 100644 --- a/app/resources/locales/sw.json +++ b/app/resources/locales/sw.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Pata Viwango vya Bei", "create_shipment.get_rates_error_body": "Imeshindwa kupata viwango vya bei:\n{error}", "create_shipment.height_label": "K ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Bima kwa thamani:", "create_shipment.insurance_none": "Hakuna", "create_shipment.insurance_tooltip": "Si lazima. Tangaza thamani ya kukatia kifurushi bima; gharama hutozwa wakati wa kununua lebo.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Chagua katika «Kwa» kifurushi kinaenda kwa nani.", "create_shipment.missing_zip_body": "Weka msimbo wa posta kwa chanzo na kwa mahali pa kwenda.", "create_shipment.missing_zip_title": "Misimbo ya posta inahitajika", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost haijarudisha viwango vyovyote vya bei kwa kifurushi hiki.", "create_shipment.no_rates_title": "Hakuna viwango vya bei", "create_shipment.non_delivery_abandon": "Achana nayo", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Hifadhi kama kifurushi", "create_shipment.save_package_dialog_label": "Ipe jina kifurushi hiki kwa matumizi ya baadaye:", "create_shipment.save_package_dialog_title": "Hifadhi kifurushi", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Lebo imehifadhiwa kwenye {path}", "create_shipment.saved_title": "Imehifadhiwa", "create_shipment.signature_adult": "Saini ya mtu mzima (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Inaonyesha rekodi za hali ya jaribio pekee. Rekodi za hali ya uzalishaji zinahifadhiwa kando.", "dashboard.spend_includes_pending_refunds": "Inajumuisha {amount} inayosubiri kurejeshwa", "dashboard.title": "

Dashibodi

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Angalia hali ya kurejesha pesa", "history.check_status_failed": "Imeshindwa kuangalia hali:\n{error}", "history.column_carrier": "Kampuni ya usafirishaji", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Namba ya ufuatiliaji", "history.confirm_insure_purchase": "Nunua bima ya {amount} kwa kifurushi hiki.", "history.confirm_refund_request": "Omba kurejeshewa pesa kwa lebo ya kifurushi hiki.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Hitilafu", "history.export_none_selected": "Kwanza chagua usafirishaji mmoja au zaidi wenye lebo iliyonunuliwa.", @@ -432,6 +438,10 @@ "history.table_group_title": "Vifurushi vilivyonunuliwa (hali hii)", "history.title": "Historia ya Vifurushi", "history.update_insurance_button": "Sasisha bima", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Maelezo", "hts_lookup.col_general_rate": "Kiwango cha Jumla", "hts_lookup.col_htsno": "Namba ya HTS", diff --git a/app/resources/locales/ta.json b/app/resources/locales/ta.json index cdf4c22..95bb81c 100644 --- a/app/resources/locales/ta.json +++ b/app/resources/locales/ta.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "கட்டணங்களைப் பெறு", "create_shipment.get_rates_error_body": "கட்டணங்களைப் பெற முடியவில்லை:\n{error}", "create_shipment.height_label": "உ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "மதிப்பிற்கு காப்பீடு:", "create_shipment.insurance_none": "இல்லை", "create_shipment.insurance_tooltip": "விருப்பத்தேர்வு. பொதியை காப்பீடு செய்ய மதிப்பை அறிவிக்கவும்; சிட்டையை வாங்கும்போது கட்டணம் விதிக்கப்படும்.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "பார்சல் யாருக்குச் செல்கிறது என்பதை «பெறுநர்» என்பதில் தேர்ந்தெடுக்கவும்.", "create_shipment.missing_zip_body": "தொடக்கம் மற்றும் சேருமிடம் ஆகிய இரண்டிற்கும் அஞ்சல் குறியீட்டை உள்ளிடவும்.", "create_shipment.missing_zip_title": "அஞ்சல் குறியீடுகள் தேவை", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "இந்த அனுப்புகைக்கு EasyPost எந்த கட்டணத்தையும் திருப்பி அளிக்கவில்லை.", "create_shipment.no_rates_title": "கட்டணங்கள் இல்லை", "create_shipment.non_delivery_abandon": "கைவிடு", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "பார்சலாகச் சேமி", "create_shipment.save_package_dialog_label": "பின்னர் மீண்டும் பயன்படுத்த இந்தப் பார்சலுக்குப் பெயரிடவும்:", "create_shipment.save_package_dialog_title": "பார்சலைச் சேமி", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "லேபிள் {path} இல் சேமிக்கப்பட்டது", "create_shipment.saved_title": "சேமிக்கப்பட்டது", "create_shipment.signature_adult": "பெரியவர் கையொப்பம் (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "சோதனை முறைப் பதிவுகள் மட்டுமே காட்டப்படுகின்றன. உற்பத்தி முறைப் பதிவுகள் தனியாக வைக்கப்படுகின்றன.", "dashboard.spend_includes_pending_refunds": "பணத்திரும்பலுக்குக் காத்திருக்கும் {amount} உட்பட", "dashboard.title": "

டாஷ்போர்டு

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "பணத்திரும்ப நிலையைச் சரிபார்", "history.check_status_failed": "நிலையைச் சரிபார்க்க முடியவில்லை:\n{error}", "history.column_carrier": "கேரியர்", @@ -404,6 +409,7 @@ "history.column_tracking_code": "டிராக்கிங் குறியீடு", "history.confirm_insure_purchase": "இந்த அனுப்புகைக்கு {amount} மதிப்புள்ள காப்பீட்டு கவரேஜை வாங்கு.", "history.confirm_refund_request": "இந்த அனுப்புகையின் லேபிளுக்குப் பணத்திரும்பக் கோரிக்கை வை.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "பிழை", "history.export_none_selected": "முதலில் வாங்கிய லேபிள் கொண்ட ஒன்று அல்லது அதற்கு மேற்பட்ட ஏற்றுமதிகளைத் தேர்ந்தெடுக்கவும்.", @@ -432,6 +438,10 @@ "history.table_group_title": "வாங்கப்பட்ட அனுப்புகைகள் (இந்த முறையில்)", "history.title": "அனுப்புகை வரலாறு", "history.update_insurance_button": "காப்பீட்டைப் புதுப்பி", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "விளக்கம்", "hts_lookup.col_general_rate": "பொது கட்டணம்", "hts_lookup.col_htsno": "HTS எண்", diff --git a/app/resources/locales/te.json b/app/resources/locales/te.json index bb2c2f5..a01639b 100644 --- a/app/resources/locales/te.json +++ b/app/resources/locales/te.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "రేట్లు పొందండి", "create_shipment.get_rates_error_body": "రేట్లను పొందలేకపోయాము:\n{error}", "create_shipment.height_label": "ఎ ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "విలువకు బీమా:", "create_shipment.insurance_none": "ఏదీ లేదు", "create_shipment.insurance_tooltip": "ఐచ్ఛికం. పార్శిల్‌కు బీమా చేయడానికి విలువను ప్రకటించండి; లేబుల్ కొనుగోలు చేసినప్పుడు కవర్‌కు రుసుము వసూలు చేయబడుతుంది.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "పార్సెల్ ఎవరికి వెళ్తోందో «గమ్యం»లో ఎంచుకోండి.", "create_shipment.missing_zip_body": "మూలం మరియు గమ్యం రెండింటికీ పోస్టల్ కోడ్ నమోదు చేయండి.", "create_shipment.missing_zip_title": "పోస్టల్ కోడ్‌లు అవసరం", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "ఈ షిప్‌మెంట్‌కు EasyPost ఎలాంటి రేట్లను తిరిగి ఇవ్వలేదు.", "create_shipment.no_rates_title": "రేట్లు లేవు", "create_shipment.non_delivery_abandon": "వదిలివేయండి", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "పార్సెల్‌గా సేవ్ చేయండి", "create_shipment.save_package_dialog_label": "తర్వాత తిరిగి ఉపయోగించడానికి ఈ పార్సెల్‌కు పేరు పెట్టండి:", "create_shipment.save_package_dialog_title": "పార్సెల్‌ను సేవ్ చేయండి", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "లేబుల్ {path}కి సేవ్ చేయబడింది", "create_shipment.saved_title": "సేవ్ చేయబడింది", "create_shipment.signature_adult": "వయోజన సంతకం (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "టెస్ట్ మోడ్ రికార్డులు మాత్రమే చూపబడుతున్నాయి. ప్రొడక్షన్ మోడ్ రికార్డులు వేరుగా ఉంచబడతాయి.", "dashboard.spend_includes_pending_refunds": "రీఫండ్ కోసం వేచి ఉన్న {amount} కలిపి", "dashboard.title": "

డాష్‌బోర్డ్

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "రీఫండ్ స్థితిని తనిఖీ చేయండి", "history.check_status_failed": "స్థితిని తనిఖీ చేయలేకపోయాము:\n{error}", "history.column_carrier": "క్యారియర్", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ట్రాకింగ్ కోడ్", "history.confirm_insure_purchase": "ఈ షిప్‌మెంట్ కోసం {amount} బీమా కవరేజీని కొనుగోలు చేయండి.", "history.confirm_refund_request": "ఈ షిప్‌మెంట్ లేబుల్ కోసం రీఫండ్‌ను అభ్యర్థించండి.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "లోపం", "history.export_none_selected": "ముందుగా కొనుగోలు చేసిన లేబుల్‌తో ఒకటి లేదా అంతకంటే ఎక్కువ రవాణాలను ఎంచుకోండి.", @@ -432,6 +438,10 @@ "history.table_group_title": "కొనుగోలు చేసిన షిప్‌మెంట్‌లు (ఈ మోడ్)", "history.title": "షిప్‌మెంట్ చరిత్ర", "history.update_insurance_button": "బీమాను నవీకరించండి", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "వివరణ", "hts_lookup.col_general_rate": "సాధారణ రేటు", "hts_lookup.col_htsno": "HTS నంబర్", diff --git a/app/resources/locales/th.json b/app/resources/locales/th.json index 36c4127..857d60c 100644 --- a/app/resources/locales/th.json +++ b/app/resources/locales/th.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "ดูอัตราค่าส่ง", "create_shipment.get_rates_error_body": "ไม่สามารถดูอัตราค่าส่งได้:\n{error}", "create_shipment.height_label": "ส ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "ประกันตามมูลค่า:", "create_shipment.insurance_none": "ไม่มี", "create_shipment.insurance_tooltip": "ไม่บังคับ ระบุมูลค่าเพื่อทำประกันพัสดุ ค่าคุ้มครองจะถูกเรียกเก็บเมื่อซื้อฉลาก", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "เลือกในช่อง ถึง ว่าจะส่งพัสดุให้ใคร", "create_shipment.missing_zip_body": "กรอกรหัสไปรษณีย์ทั้งต้นทางและปลายทาง", "create_shipment.missing_zip_title": "ต้องระบุรหัสไปรษณีย์", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ไม่พบอัตราค่าส่งสำหรับพัสดุนี้", "create_shipment.no_rates_title": "ไม่มีอัตราค่าส่ง", "create_shipment.non_delivery_abandon": "ทิ้งพัสดุ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "บันทึกเป็นพัสดุ", "create_shipment.save_package_dialog_label": "ตั้งชื่อพัสดุนี้เพื่อนำมาใช้ซ้ำภายหลัง:", "create_shipment.save_package_dialog_title": "บันทึกพัสดุ", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "บันทึกใบปะหน้าไปยัง {path} แล้ว", "create_shipment.saved_title": "บันทึกแล้ว", "create_shipment.signature_adult": "ลายเซ็นผู้ใหญ่ (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "แสดงเฉพาะข้อมูลในโหมดทดสอบ ข้อมูลในโหมดใช้งานจริงจัดเก็บแยกต่างหาก", "dashboard.spend_includes_pending_refunds": "รวม {amount} ที่รอการคืนเงิน", "dashboard.title": "

แดชบอร์ด

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "ตรวจสอบสถานะการคืนเงิน", "history.check_status_failed": "ไม่สามารถตรวจสอบสถานะได้:\n{error}", "history.column_carrier": "ผู้ให้บริการขนส่ง", @@ -404,6 +409,7 @@ "history.column_tracking_code": "เลขพัสดุ", "history.confirm_insure_purchase": "ซื้อความคุ้มครองประกันจำนวน {amount} สำหรับพัสดุนี้", "history.confirm_refund_request": "ขอคืนเงินสำหรับใบปะหน้าของพัสดุนี้", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "ข้อผิดพลาด", "history.export_none_selected": "โปรดเลือกการจัดส่งที่ซื้อฉลากแล้วอย่างน้อยหนึ่งรายการก่อน", @@ -432,6 +438,10 @@ "history.table_group_title": "พัสดุที่ซื้อแล้ว (โหมดนี้)", "history.title": "ประวัติการจัดส่ง", "history.update_insurance_button": "อัปเดตประกัน", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "คำอธิบาย", "hts_lookup.col_general_rate": "อัตราทั่วไป", "hts_lookup.col_htsno": "หมายเลข HTS", diff --git a/app/resources/locales/tr.json b/app/resources/locales/tr.json index 57e72b7..753ac69 100644 --- a/app/resources/locales/tr.json +++ b/app/resources/locales/tr.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Ücretleri Al", "create_shipment.get_rates_error_body": "Ücretler alınamadı:\n{error}", "create_shipment.height_label": "Y ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Değer için sigorta:", "create_shipment.insurance_none": "Yok", "create_shipment.insurance_tooltip": "İsteğe bağlı. Paketi sigortalamak için bir değer beyan edin; teminat ücreti etiket satın alınırken tahsil edilir.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Alıcı alanında paketin kime gideceğini seçin.", "create_shipment.missing_zip_body": "Hem gönderen hem de alıcı için bir posta kodu girin.", "create_shipment.missing_zip_title": "Posta kodu gerekli", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost bu gönderi için ücret döndürmedi.", "create_shipment.no_rates_title": "Ücret yok", "create_shipment.non_delivery_abandon": "Terk et", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Paket olarak kaydet", "create_shipment.save_package_dialog_label": "Daha sonra tekrar kullanmak için bu pakete bir ad verin:", "create_shipment.save_package_dialog_title": "Paketi kaydet", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Etiket {path} konumuna kaydedildi", "create_shipment.saved_title": "Kaydedildi", "create_shipment.signature_adult": "Yetişkin imzası (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Yalnızca test modu kayıtları gösteriliyor. Üretim modu kayıtları ayrı tutulur.", "dashboard.spend_includes_pending_refunds": "{amount} iade bekliyor, bu tutara dahil", "dashboard.title": "

Kontrol Paneli

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "İade durumunu kontrol et", "history.check_status_failed": "Durum kontrol edilemedi:\n{error}", "history.column_carrier": "Kargo Şirketi", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Takip numarası", "history.confirm_insure_purchase": "Bu gönderi için {amount} tutarında sigorta teminatı satın al.", "history.confirm_refund_request": "Bu gönderinin etiketi için iade talep et.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Hata", "history.export_none_selected": "Önce satın alınmış etiketi olan bir veya daha fazla gönderi seçin.", @@ -432,6 +438,10 @@ "history.table_group_title": "Satın alınan gönderiler (bu mod)", "history.title": "Gönderi Geçmişi", "history.update_insurance_button": "Sigortayı güncelle", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Açıklama", "hts_lookup.col_general_rate": "Genel Oran", "hts_lookup.col_htsno": "HTS Numarası", diff --git a/app/resources/locales/uk.json b/app/resources/locales/uk.json index b374422..0874dfc 100644 --- a/app/resources/locales/uk.json +++ b/app/resources/locales/uk.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Отримати тарифи", "create_shipment.get_rates_error_body": "Не вдалося отримати тарифи:\n{error}", "create_shipment.height_label": "В ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Застрахувати на суму:", "create_shipment.insurance_none": "Немає", "create_shipment.insurance_tooltip": "Необов'язково. Укажіть вартість для страхування посилки; покриття сплачується під час придбання етикетки.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "У полі «Кому» виберіть, кому надсилається посилка.", "create_shipment.missing_zip_body": "Введіть поштовий індекс відправника та одержувача.", "create_shipment.missing_zip_title": "Потрібні поштові індекси", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost не повернув жодних тарифів для цього відправлення.", "create_shipment.no_rates_title": "Немає тарифів", "create_shipment.non_delivery_abandon": "Відмовитися від відправлення", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Зберегти як посилку", "create_shipment.save_package_dialog_label": "Назвіть цю посилку для повторного використання пізніше:", "create_shipment.save_package_dialog_title": "Зберегти посилку", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Етикетку збережено в {path}", "create_shipment.saved_title": "Збережено", "create_shipment.signature_adult": "Підпис дорослого (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Показано лише записи тестового режиму. Записи робочого режиму зберігаються окремо.", "dashboard.spend_includes_pending_refunds": "Зокрема {amount} очікують повернення", "dashboard.title": "

Панель приладів

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Перевірити статус повернення", "history.check_status_failed": "Не вдалося перевірити статус:\n{error}", "history.column_carrier": "Перевізник", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Номер відстеження", "history.confirm_insure_purchase": "Придбати страхове покриття на суму {amount} для цього відправлення.", "history.confirm_refund_request": "Запросити повернення коштів за етикетку цього відправлення.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Помилка", "history.export_none_selected": "Спершу виберіть одне або кілька відправлень із придбаною етикеткою.", @@ -432,6 +438,10 @@ "history.table_group_title": "Придбані відправлення (цей режим)", "history.title": "Історія відправлень", "history.update_insurance_button": "Оновити страхування", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Опис", "hts_lookup.col_general_rate": "Загальний тариф", "hts_lookup.col_htsno": "Номер HTS", diff --git a/app/resources/locales/ur.json b/app/resources/locales/ur.json index b8e068a..d6bed46 100644 --- a/app/resources/locales/ur.json +++ b/app/resources/locales/ur.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "نرخ حاصل کریں", "create_shipment.get_rates_error_body": "نرخ حاصل نہیں کیے جا سکے:\n{error}", "create_shipment.height_label": "ا ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "اس مالیت پر بیمہ:", "create_shipment.insurance_none": "کوئی نہیں", "create_shipment.insurance_tooltip": "اختیاری۔ پارسل کے بیمے کے لیے مالیت درج کریں؛ کور کی قیمت لیبل خریدتے وقت وصول کی جاتی ہے۔", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«بنام» میں منتخب کریں کہ پارسل کس کو جا رہا ہے۔", "create_shipment.missing_zip_body": "مبدأ اور منزل دونوں کے لیے پوسٹل کوڈ درج کریں۔", "create_shipment.missing_zip_title": "پوسٹل کوڈ درکار ہیں", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost نے اس شپمنٹ کے لیے کوئی نرخ واپس نہیں کیا۔", "create_shipment.no_rates_title": "کوئی نرخ نہیں", "create_shipment.non_delivery_abandon": "ترک کر دیں", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "پارسل کے طور پر محفوظ کریں", "create_shipment.save_package_dialog_label": "بعد میں دوبارہ استعمال کے لیے اس پارسل کو نام دیں:", "create_shipment.save_package_dialog_title": "پارسل محفوظ کریں", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "لیبل {path} میں محفوظ کر دیا گیا", "create_shipment.saved_title": "محفوظ شدہ", "create_shipment.signature_adult": "بالغ کے دستخط (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "صرف ٹیسٹ موڈ کے ریکارڈز دکھائے جا رہے ہیں۔ پروڈکشن موڈ کے ریکارڈز الگ رکھے جاتے ہیں۔", "dashboard.spend_includes_pending_refunds": "رقم واپسی کی منتظر {amount} شامل ہے", "dashboard.title": "

ڈیش بورڈ

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "رقم واپسی کی صورتحال دیکھیں", "history.check_status_failed": "صورتحال چیک نہیں کی جا سکی:\n{error}", "history.column_carrier": "کیریئر", @@ -404,6 +409,7 @@ "history.column_tracking_code": "ٹریکنگ کوڈ", "history.confirm_insure_purchase": "اس شپمنٹ کے لیے {amount} کی بیمہ کوریج خریدیں۔", "history.confirm_refund_request": "اس شپمنٹ کے لیبل کے لیے رقم واپسی کی درخواست کریں۔", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "خرابی", "history.export_none_selected": "پہلے خریدے گئے لیبل والی ایک یا زیادہ ترسیلات منتخب کریں۔", @@ -432,6 +438,10 @@ "history.table_group_title": "خریدی گئی شپمنٹس (اس موڈ میں)", "history.title": "شپمنٹ کی تاریخ", "history.update_insurance_button": "بیمہ اپ ڈیٹ کریں", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "تفصیل", "hts_lookup.col_general_rate": "عمومی نرخ", "hts_lookup.col_htsno": "HTS نمبر", diff --git a/app/resources/locales/uz.json b/app/resources/locales/uz.json index bd4a08e..670c052 100644 --- a/app/resources/locales/uz.json +++ b/app/resources/locales/uz.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Tariflarni olish", "create_shipment.get_rates_error_body": "Tariflarni olib bo'lmadi:\n{error}", "create_shipment.height_label": "B ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Ushbu qiymatga sugʻurta:", "create_shipment.insurance_none": "Yoʻq", "create_shipment.insurance_tooltip": "Ixtiyoriy. Posilkani sugʻurtalash uchun qiymatni koʻrsating; qopqoq haqi yorliq sotib olinganda olinadi.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "«Kimga» maydonida posilka kimga yuborilishini tanlang.", "create_shipment.missing_zip_body": "Jo‘natish va yetkazish manzillari uchun pochta indeksini kiriting.", "create_shipment.missing_zip_title": "Pochta indekslari talab qilinadi", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost ushbu jo'natma uchun hech qanday tarif qaytarmadi.", "create_shipment.no_rates_title": "Tariflar yo'q", "create_shipment.non_delivery_abandon": "Voz kechish", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Pochta jo'natmasi sifatida saqlash", "create_shipment.save_package_dialog_label": "Keyinroq qayta ishlatish uchun bu jo'natmaga nom bering:", "create_shipment.save_package_dialog_title": "Pochta jo'natmasini saqlash", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Yorliq {path} manziliga saqlandi", "create_shipment.saved_title": "Saqlandi", "create_shipment.signature_adult": "Kattalar imzosi (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Faqat sinov rejimi yozuvlari ko'rsatilmoqda. Ishlab chiqarish rejimi yozuvlari alohida saqlanadi.", "dashboard.spend_includes_pending_refunds": "Shundan {amount} qaytarilishini kutmoqda", "dashboard.title": "

Boshqaruv paneli

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Qaytarish holatini tekshirish", "history.check_status_failed": "Holatni tekshirib bo'lmadi:\n{error}", "history.column_carrier": "Tashuvchi", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Kuzatuv raqami", "history.confirm_insure_purchase": "Ushbu jo'natma uchun {amount} miqdorida sug'urta qoplamasini sotib oling.", "history.confirm_refund_request": "Ushbu jo'natma yorlig'i uchun pulni qaytarishni so'rang.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Xatolik", "history.export_none_selected": "Avval sotib olingan yorlig'i bor bir yoki bir nechta jo'natmani tanlang.", @@ -432,6 +438,10 @@ "history.table_group_title": "Sotib olingan jo'natmalar (ushbu rejim)", "history.title": "Jo'natmalar tarixi", "history.update_insurance_button": "Sug'urtani yangilash", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Tavsif", "hts_lookup.col_general_rate": "Umumiy stavka", "hts_lookup.col_htsno": "HTS raqami", diff --git a/app/resources/locales/vi.json b/app/resources/locales/vi.json index 9605017..6365511 100644 --- a/app/resources/locales/vi.json +++ b/app/resources/locales/vi.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Lấy Cước Phí", "create_shipment.get_rates_error_body": "Không thể lấy cước phí:\n{error}", "create_shipment.height_label": "C ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Bảo hiểm theo giá trị:", "create_shipment.insurance_none": "Không", "create_shipment.insurance_tooltip": "Tùy chọn. Khai báo giá trị để bảo hiểm bưu kiện; phí bảo hiểm được tính khi mua nhãn.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Chọn ở mục Đến người sẽ nhận bưu kiện.", "create_shipment.missing_zip_body": "Nhập mã bưu chính cho cả nơi gửi và nơi nhận.", "create_shipment.missing_zip_title": "Cần có mã bưu chính", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost không trả về cước phí nào cho lô hàng này.", "create_shipment.no_rates_title": "Không có cước phí", "create_shipment.non_delivery_abandon": "Từ bỏ", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Lưu dưới dạng kiện hàng", "create_shipment.save_package_dialog_label": "Đặt tên cho kiện hàng này để dùng lại sau:", "create_shipment.save_package_dialog_title": "Lưu kiện hàng", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Đã lưu nhãn vào {path}", "create_shipment.saved_title": "Đã lưu", "create_shipment.signature_adult": "Chữ ký người lớn (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Chỉ hiển thị bản ghi ở chế độ thử nghiệm. Bản ghi ở chế độ sản xuất được lưu riêng.", "dashboard.spend_includes_pending_refunds": "Bao gồm {amount} đang chờ hoàn tiền", "dashboard.title": "

Bảng Điều Khiển

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Kiểm tra trạng thái hoàn tiền", "history.check_status_failed": "Không thể kiểm tra trạng thái:\n{error}", "history.column_carrier": "Đơn vị vận chuyển", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Mã vận đơn", "history.confirm_insure_purchase": "Mua bảo hiểm trị giá {amount} cho lô hàng này.", "history.confirm_refund_request": "Yêu cầu hoàn tiền cho nhãn vận chuyển của lô hàng này.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Lỗi", "history.export_none_selected": "Trước tiên hãy chọn một hoặc nhiều lô hàng đã mua nhãn.", @@ -432,6 +438,10 @@ "history.table_group_title": "Lô hàng đã mua (chế độ này)", "history.title": "Lịch Sử Lô Hàng", "history.update_insurance_button": "Cập nhật bảo hiểm", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Mô tả", "hts_lookup.col_general_rate": "Thuế suất chung", "hts_lookup.col_htsno": "Mã số HTS", diff --git a/app/resources/locales/yo.json b/app/resources/locales/yo.json index 1c415ae..ebf459a 100644 --- a/app/resources/locales/yo.json +++ b/app/resources/locales/yo.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Gba Owó Ìfìránṣẹ́", "create_shipment.get_rates_error_body": "A kò lè gba owó ìfìránṣẹ́:\n{error}", "create_shipment.height_label": "Gí ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Ṣe iṣẹ́ àbò fún iye:", "create_shipment.insurance_none": "Kò sí", "create_shipment.insurance_tooltip": "Àṣàyàn. Sọ iye láti ṣe iṣẹ́ àbò fún àpótí; owó àbò ni a ń gbà nígbà tí o bá ra àmì.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Yan ní «Sí» ẹni tí a ń fi ẹrù náà ránṣẹ́ sí.", "create_shipment.missing_zip_body": "Tẹ kóòdù ìfìwéránṣẹ́ sí ibi ìbẹ̀rẹ̀ àti ibi tí a ń lọ.", "create_shipment.missing_zip_title": "A nílò kóòdù ìfìwéránṣẹ́", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost kò dá owó ìfìránṣẹ́ kankan padà fún ìfìránṣẹ́ yìí.", "create_shipment.no_rates_title": "Kò sí owó ìfìránṣẹ́", "create_shipment.non_delivery_abandon": "Fi sílẹ̀", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Fi pamọ́ gẹ́gẹ́ bí ẹrù", "create_shipment.save_package_dialog_label": "Fun ẹrù yìí ní orúkọ fún àtúnlò nígbà mìíràn:", "create_shipment.save_package_dialog_title": "Fi ẹrù pamọ́", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "A ti fi àmì pamọ́ sí {path}", "create_shipment.saved_title": "A ti fi pamọ́", "create_shipment.signature_adult": "Ìbúwọlú àgbà (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Àwọn àkọsílẹ̀ ipò ìdánwò nìkan ni a ń fihàn. A ń tọ́jú àwọn àkọsílẹ̀ ipò ìṣelọ́pọ̀ lọ́tọ̀.", "dashboard.spend_includes_pending_refunds": "Ó ní {amount} tí ó ń dúró de ìdápadà owó nínú", "dashboard.title": "

Pátákó Ìdarí

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Ṣàyẹ̀wò ipò ìdápadà owó", "history.check_status_failed": "A kò lè ṣàyẹ̀wò ipò:\n{error}", "history.column_carrier": "Olùgbé", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Kóòdù ìtọpinpin", "history.confirm_insure_purchase": "Ra ààbò ìṣeduro ti {amount} fún ìfìránṣẹ́ yìí.", "history.confirm_refund_request": "Bèèrè fún ìdápadà owó fún àmì ìfìránṣẹ́ yìí.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Àṣìṣe", "history.export_none_selected": "Kọ́kọ́ yan ọjà kan tàbí jù bẹ́ẹ̀ lọ tí ó ní àmì tí a ti rà.", @@ -432,6 +438,10 @@ "history.table_group_title": "Àwọn ìfìránṣẹ́ tí a ti rà (ipò yìí)", "history.title": "Ìtàn Ìfìránṣẹ́", "history.update_insurance_button": "Tún ìṣeduro ṣe", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Àpèjúwe", "hts_lookup.col_general_rate": "Owó gbogbogbò", "hts_lookup.col_htsno": "Nọ́mbà HTS", diff --git a/app/resources/locales/zh.json b/app/resources/locales/zh.json index 08c3c74..c0b23f0 100644 --- a/app/resources/locales/zh.json +++ b/app/resources/locales/zh.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "获取运费", "create_shipment.get_rates_error_body": "无法获取运费:\n{error}", "create_shipment.height_label": "高 ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "按价值投保:", "create_shipment.insurance_none": "无", "create_shipment.insurance_tooltip": "可选。申报包裹的投保价值;保费在购买面单时收取。", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "请在“收件人”中选择包裹寄给谁。", "create_shipment.missing_zip_body": "请输入寄件地和收件地的邮政编码。", "create_shipment.missing_zip_title": "需要邮政编码", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "EasyPost 未返回此运单的任何运费。", "create_shipment.no_rates_title": "无可用运费", "create_shipment.non_delivery_abandon": "放弃", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "另存为包裹", "create_shipment.save_package_dialog_label": "为此包裹命名以便日后重复使用:", "create_shipment.save_package_dialog_title": "保存包裹", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "面单已保存至 {path}", "create_shipment.saved_title": "已保存", "create_shipment.signature_adult": "成人签名 (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "仅显示测试模式记录。生产模式记录单独保存。", "dashboard.spend_includes_pending_refunds": "其中 {amount} 正在等待退款", "dashboard.title": "

仪表盘

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "查看退款状态", "history.check_status_failed": "无法查看状态:\n{error}", "history.column_carrier": "承运商", @@ -404,6 +409,7 @@ "history.column_tracking_code": "追踪号", "history.confirm_insure_purchase": "为此运单购买 {amount} 的保险保障。", "history.confirm_refund_request": "为此运单标签申请退款。", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "错误", "history.export_none_selected": "请先选择一个或多个已购买标签的货件。", @@ -432,6 +438,10 @@ "history.table_group_title": "已购买运单(当前模式)", "history.title": "运单历史", "history.update_insurance_button": "更新保险", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "说明", "hts_lookup.col_general_rate": "一般税率", "hts_lookup.col_htsno": "HTS 编号", diff --git a/app/resources/locales/zu.json b/app/resources/locales/zu.json index 67dab57..c07410c 100644 --- a/app/resources/locales/zu.json +++ b/app/resources/locales/zu.json @@ -300,6 +300,7 @@ "create_shipment.get_rates_button": "Thola amanani", "create_shipment.get_rates_error_body": "Ayikwazanga ukuthola amanani:\n{error}", "create_shipment.height_label": "P ({unit}):", + "create_shipment.inline_missing_street_city": "Enter at least a street and city for the recipient.", "create_shipment.insurance_label": "Umshwalense ngenani:", "create_shipment.insurance_none": "Lutho", "create_shipment.insurance_tooltip": "Okukhethwayo. Bika inani lokushwalensa iphasela; imali yokumboza ikhokhwa lapho uthenga ilebula.", @@ -319,6 +320,7 @@ "create_shipment.missing_recipient_body": "Khetha ku-«Kuya» ukuthi iphasela liya kubani.", "create_shipment.missing_zip_body": "Faka ikhodi yeposi yalapho kuthunyelwa khona nalapho kuthunyelwe kusuka khona.", "create_shipment.missing_zip_title": "Amakhodi eposi ayadingeka", + "create_shipment.new_recipient_option": "Enter new recipient…", "create_shipment.no_rates_body": "I-EasyPost ayibuyiselanga amanani ale mpahla ethunyelwe.", "create_shipment.no_rates_title": "Awekho amanani", "create_shipment.non_delivery_abandon": "Yeka", @@ -355,6 +357,7 @@ "create_shipment.save_package_button": "Gcina njengephakethe", "create_shipment.save_package_dialog_label": "Nika leli phakethe igama ukuze uliqale futhi kamuva:", "create_shipment.save_package_dialog_title": "Gcina iphakethe", + "create_shipment.save_to_address_book": "Save to address book", "create_shipment.saved_body": "Ilebula ligcinwe ku-{path}", "create_shipment.saved_title": "Kugciniwe", "create_shipment.signature_adult": "Isignesha yomdala (18+)", @@ -391,6 +394,8 @@ "dashboard.scope_test": "Kuboniswa amarekhodi emodi yokuhlola kuphela. Amarekhodi emodi yokusebenza agcinwa ngokwehlukana.", "dashboard.spend_includes_pending_refunds": "Kufaka {amount} elindele ukubuyiselwa", "dashboard.title": "

Ideshibhodi

", + "history.cd_manifest_created_body": "Click & Drop manifest created. Open the PDF?", + "history.cd_manifest_pending_body": "Click & Drop manifest submitted. It is still being generated — check back shortly.", "history.check_refund_status_button": "Hlola isimo semali ebuyiselwe", "history.check_status_failed": "Ayikwazanga ukuhlola isimo:\n{error}", "history.column_carrier": "Inkampani ethuthayo", @@ -404,6 +409,7 @@ "history.column_tracking_code": "Ikhodi yokulandelela", "history.confirm_insure_purchase": "Thenga ukumbozwa komshwalense we-{amount} kule mpahla ethunyelwe.", "history.confirm_refund_request": "Cela imali ebuyiselwe yelebula yale mpahla ethunyelwe.", + "history.confirm_void_order": "Void this Click & Drop order? This cancels the label and cannot be undone.", "history.create_manifest_button": "Create Manifest", "history.error_title": "Iphutha", "history.export_none_selected": "Qala ukhethe okukodwa noma okuningi okuthunyelwe okunelebula elithengiwe.", @@ -432,6 +438,10 @@ "history.table_group_title": "Izimpahla ezithengiwe (le modi)", "history.title": "Umlando wezimpahla", "history.update_insurance_button": "Buyekeza umshwalense", + "history.void_complete_body": "The Click & Drop order has been voided and the label cancelled.", + "history.void_complete_title": "Order voided", + "history.void_failed": "Could not void order:\n{error}", + "history.void_order_button": "Void order", "hts_lookup.col_description": "Incazelo", "hts_lookup.col_general_rate": "Izinga elivamile", "hts_lookup.col_htsno": "Inombolo ye-HTS", diff --git a/app/services/click_drop.py b/app/services/click_drop.py index ba47a42..b5df477 100644 --- a/app/services/click_drop.py +++ b/app/services/click_drop.py @@ -7,8 +7,7 @@ from __future__ import annotations -import json -import os +import logging from dataclasses import dataclass from pathlib import Path from typing import Optional @@ -17,9 +16,12 @@ from app.core import click_drop_client as api from app.core.click_drop_client import ClickDropError from app.core.client import client_manager +from app.core.countries import to_alpha3 from app.core.credential_store import load_credentials from app.core.db import db_cursor +logger = logging.getLogger(__name__) + # ── Normalised rate (duck-types EasyPost's rate object for the UI) ──── @@ -75,7 +77,9 @@ def test_connection() -> dict: "LargeLetter": "largeLetter", "SmallParcel": "smallParcel", "MediumParcel": "mediumParcel", + "LargeParcel": "largeParcel", "Parcel": "parcel", + "Documents": "documents", } @@ -113,7 +117,7 @@ def fetch_services( return [] try: - params: dict = {"country_code": country_code} + params: dict = {"country_code": to_alpha3(country_code)} if postcode: params["postcode"] = postcode if weight_grams: @@ -123,25 +127,56 @@ def fetch_services( raw = api.get_services(key, **params) except Exception: + logger.exception("Click & Drop services fetch failed") + return [] + + return _parse_services(raw, weight_grams) + + +def _parse_services(raw, weight_grams: int = 0) -> list[ClickDropRate]: + """Normalise the Click & Drop /services response into ClickDropRate objects. + + The API returns nested carrier groups, each with a ``services`` list. + """ + if not raw: + return [] + + services: list[dict] = [] + if isinstance(raw, dict): + services = raw.get("services", []) + elif isinstance(raw, list): + for item in raw: + if not isinstance(item, dict): + continue + if "serviceCode" in item: + services.append(item) + elif "services" in item: + services.extend(item.get("services", [])) + else: + logger.warning("Unexpected Click & Drop services response type: %s", type(raw)) return [] + fallback_fmt = _to_cd_format(weight_grams / 28.3495) if weight_grams else "" rates: list[ClickDropRate] = [] - for carrier_group in raw: - for svc in carrier_group.get("services", []): - code = svc.get("serviceCode", "") - name = svc.get("serviceName", code) - rates.append( - ClickDropRate( - id=f"cd_{code}", - carrier=_CARRIER_CODE, - service=name, - rate="0.00", - currency="GBP", - delivery_days=None, - service_code=code, - package_format="", - ) + seen: set[str] = set() + for svc in services: + code = svc.get("serviceCode", "") + if not code or code in seen: + continue + seen.add(code) + name = svc.get("serviceName", code) + rates.append( + ClickDropRate( + id=f"cd_{code}", + carrier=_CARRIER_CODE, + service=name, + rate="0.00", + currency="GBP", + delivery_days=None, + service_code=code, + package_format=_FORMAT_MAP.get(fallback_fmt, fallback_fmt), ) + ) return rates @@ -160,10 +195,18 @@ def buy_click_drop( sender: dict | None = None, packages: list[dict], order_reference: str = "", + consequential_loss: int = 0, ) -> ClickDropOrder: """Create a Click & Drop order with inline label (OBA).""" key = _api_key() + if "countryCode" in recipient: + recipient = {**recipient, "countryCode": to_alpha3(recipient["countryCode"])} + + postage: dict = {"serviceCode": service_code} + if consequential_loss > 0: + postage["consequentialLoss"] = consequential_loss + item: dict = { "orderReference": order_reference or None, "recipient": {"address": recipient}, @@ -172,7 +215,7 @@ def buy_click_drop( "subtotal": 0, "shippingCostCharged": 0, "total": 0, - "postageDetails": {"serviceCode": service_code}, + "postageDetails": postage, "label": {"includeLabelInResponse": True, "includeCN": True}, } if sender: @@ -279,6 +322,182 @@ def save_click_drop_locally( ) +# ── Bulk order creation (batch) ─────────────────────────────────────── + +@dataclass +class BulkClickDropResult: + created: list[ClickDropOrder] + failed: list[dict] + + +def bulk_buy_click_drop( + *, + rows: list, + service_code: str, + from_address: dict | None = None, +) -> BulkClickDropResult: + """Create Click & Drop orders in bulk from batch-imported rows. + + Click & Drop accepts up to 2000 items per call. Each ``row`` is a + BatchRow-like object with a ``.fields`` dict carrying the CSV columns. + """ + key = _api_key() + order_date = _iso_now() + + items: list[dict] = [] + for row in rows: + f = row.fields + weight_oz = float(f.get("weight", 0) or 0) + weight_g = int(weight_oz * 28.3495) if weight_oz else 0 + fmt = _to_cd_format(weight_oz) + country_raw = (f.get("to_country", "") or "GB").upper() + recipient = { + "fullName": (f.get("to_name", "") or "").strip(), + "companyName": (f.get("to_company", "") or "").strip(), + "addressLine1": (f.get("to_street1", "") or "").strip(), + "addressLine2": (f.get("to_street2", "") or "").strip(), + "addressLine3": "", + "city": (f.get("to_city", "") or "").strip(), + "county": (f.get("to_state", "") or "").strip(), + "postcode": (f.get("to_zip", "") or "").strip(), + "countryCode": to_alpha3(country_raw), + "phoneNumber": (f.get("to_phone", "") or "").strip(), + "emailAddress": (f.get("to_email", "") or "").strip(), + } + pkg: dict = {"weightInGrams": weight_g, "packageFormatIdentifier": fmt} + length = float(f.get("length", 0) or 0) + width = float(f.get("width", 0) or 0) + height = float(f.get("height", 0) or 0) + if length and width and height: + pkg["heightInMms"] = round(height * 25.4) + pkg["widthInMms"] = round(width * 25.4) + pkg["depthInMms"] = round(length * 25.4) + + item: dict = { + "orderReference": f.get("reference", "") or None, + "recipient": {"address": recipient}, + "packages": [pkg], + "orderDate": order_date, + "subtotal": 0, + "shippingCostCharged": 0, + "total": 0, + "postageDetails": {"serviceCode": service_code}, + "label": {"includeLabelInResponse": True, "includeCN": True}, + } + if from_address: + item["sender"] = from_address + items.append(item) + + resp = api.create_orders(key, items=items) + + created_orders: list[ClickDropOrder] = [] + for order in (resp or {}).get("createdOrders", []): + order_id = order["orderIdentifier"] + tracking = order.get("trackingNumber") + label_b64 = order.get("label") + label_pdf = api.decode_label_from_response(label_b64) + label_path = None + if label_pdf: + ensure_app_data_dir() + label_path = str(_labels_dir() / f"cd_{order_id}.pdf") + Path(label_path).write_bytes(label_pdf) + created_orders.append(ClickDropOrder( + order_identifier=order_id, + tracking_number=tracking, + label_pdf=label_pdf, + label_pdf_path=label_path, + service_code=service_code, + service_name=service_code, + )) + + failed_orders = (resp or {}).get("failedOrders", []) + return BulkClickDropResult(created=created_orders, failed=failed_orders) + + +# ── Order void / cancel ────────────────────────────────────────── + +def void_click_drop_order(order_identifier: int) -> None: + """Void (cancel) a Click & Drop order. Deletes the label.""" + key = _api_key() + api.delete_order(key, order_identifier) + + with db_cursor() as cur: + cur.execute( + "UPDATE click_drop_orders SET status = ? WHERE order_identifier = ?", + ("voided", order_identifier), + ) + cur.execute( + "UPDATE shipments SET refund_status = ? WHERE id = ?", + ("voided", f"cd_{order_identifier}"), + ) + + +# ── CD-specific manifest ──────────────────────────────────────── + +@dataclass +class ClickDropManifest: + manifest_id: int | None + document_pdf: bytes | None + pdf_path: str | None + + +def create_click_drop_manifest() -> ClickDropManifest: + """Manifest all eligible Click & Drop orders. + + Returns 201 with a PDF or 202 if the manifest is still being + generated (call ``get_click_drop_manifest`` to retrieve it later). + """ + key = _api_key() + resp = api.create_manifest(key) + + manifest_id = (resp or {}).get("manifestId") + doc_b64 = (resp or {}).get("documentPdf") + pdf_bytes = None + pdf_path = None + if doc_b64: + import base64 + try: + pdf_bytes = base64.b64decode(doc_b64) + except Exception: + pass + if pdf_bytes: + ensure_app_data_dir() + pdf_path = str(_labels_dir() / f"manifest_{manifest_id or 'latest'}.pdf") + Path(pdf_path).write_bytes(pdf_bytes) + + return ClickDropManifest( + manifest_id=manifest_id, + document_pdf=pdf_bytes, + pdf_path=pdf_path, + ) + + +def get_click_drop_manifest(manifest_id: int) -> ClickDropManifest: + """Retrieve a previously created manifest by ID.""" + key = _api_key() + resp = api.get_manifest(key, manifest_id) + + doc_b64 = (resp or {}).get("documentPdf") + pdf_bytes = None + pdf_path = None + if doc_b64: + import base64 + try: + pdf_bytes = base64.b64decode(doc_b64) + except Exception: + pass + if pdf_bytes: + ensure_app_data_dir() + pdf_path = str(_labels_dir() / f"manifest_{manifest_id}.pdf") + Path(pdf_path).write_bytes(pdf_bytes) + + return ClickDropManifest( + manifest_id=manifest_id, + document_pdf=pdf_bytes, + pdf_path=pdf_path, + ) + + # ── Utilities ───────────────────────────────────────────────────────── def _iso_now() -> str: diff --git a/app/services/shipments.py b/app/services/shipments.py index ba8ace5..1e908bd 100644 --- a/app/services/shipments.py +++ b/app/services/shipments.py @@ -21,8 +21,9 @@ def preferred_label_options() -> dict: def create_shipment( *, - to_address_id: str, + to_address_id: str = "", from_address_id: str, + to_address: Optional[dict] = None, weight: float, length: Optional[float] = None, width: Optional[float] = None, @@ -32,9 +33,11 @@ def create_shipment( customs_info: Optional[dict] = None, delivery_confirmation: Optional[str] = None, ): - """Create a shipment and get back live carrier rates. References existing - verified addresses by EasyPost id rather than re-submitting full address - fields. + """Create a shipment and get back live carrier rates. + + The recipient can be given as ``to_address_id`` (an EasyPost address id + from the address book) *or* ``to_address`` (a dict of address fields for + a new recipient entered inline). Exactly one of `predefined_package` (a carrier box/envelope code, e.g. "FedExPak" — see app/services/packages.py) or `length`/`width`/`height` @@ -56,16 +59,13 @@ def create_shipment( else: parcel.update({"length": length, "width": width, "height": height}) - # Merge the signature option into the user's label-format options rather - # than replacing them, and only when one is chosen (an empty value would - # otherwise clear whatever carriers default to). options = preferred_label_options() if delivery_confirmation: options["delivery_confirmation"] = delivery_confirmation client = client_manager.get_client() params = dict( - to_address={"id": to_address_id}, + to_address=to_address if to_address else {"id": to_address_id}, from_address={"id": from_address_id}, parcel=parcel, reference=reference or None, diff --git a/app/ui/views/batch_view.py b/app/ui/views/batch_view.py index 927d17a..e6d5def 100644 --- a/app/ui/views/batch_view.py +++ b/app/ui/views/batch_view.py @@ -6,12 +6,14 @@ carrier and service are declared up front through the ServicePicker instead. """ +import logging from pathlib import Path -from PySide6.QtCore import QTimer +from PySide6.QtCore import Qt, QTimer from PySide6.QtWidgets import ( QCheckBox, QComboBox, + QCompleter, QGridLayout, QFileDialog, QFormLayout, @@ -53,6 +55,12 @@ write_csv_template, write_xlsx_template, ) +from app.core.countries import to_alpha3 +from app.services.carriers import carrier_matches +from app.services.click_drop import ( + bulk_buy_click_drop, + save_click_drop_locally, +) from app.services.label_sheets import build_combined_labels from app.services.manifests import create_manifest, save_manifest_locally from app.services.packages import predefined_package_choices @@ -63,6 +71,8 @@ from app.ui.widgets.review_nudge import schedule_review_prompt from app.ui.widgets.service_picker import ServicePicker +logger = logging.getLogger(__name__) + # States EasyPost is still working through. Batch creation and purchase are both # asynchronous, so the app polls until the state settles rather than leaving the # user to press Refresh and guess. @@ -157,15 +167,24 @@ def _build_import_group(self) -> QGroupBox: row = QHBoxLayout() self._from_combo = QComboBox() - # A combo will not shrink below the width of its longest address unless - # told it may, so in German — where "Vorlage herunterladen" and - # "Datei wählen…" are half again as long as their English labels — the - # row overflowed and cut the second button off the edge of the window. - # The address is the elastic part here; the buttons are not. self._from_combo.setMinimumContentsLength(12) self._from_combo.setSizeAdjustPolicy( QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon ) + self._from_combo.setEditable(True) + self._from_combo.setInsertPolicy(QComboBox.InsertPolicy.NoInsert) + completer = self._from_combo.completer() + if completer is not None: + completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) + completer.setFilterMode(Qt.MatchFlag.MatchContains) + completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) + le = self._from_combo.lineEdit() + if le: + def _restore(c=self._from_combo): + idx = c.currentIndex() + if idx >= 0: + c.setEditText(c.itemText(idx)) + le.editingFinished.connect(_restore) template_btn = QPushButton(tr("batch_shipments.download_template_button")) template_btn.clicked.connect(self._on_download_template) browse_btn = QPushButton(tr("batch_shipments.choose_csv_button")) @@ -555,6 +574,11 @@ def _on_create_batch(self) -> None: return self._selection = selection + + if selection and carrier_matches(selection.carrier, "ClickDrop"): + self._on_create_cd_batch(selection) + return + self._create_batch_btn.setEnabled(False) self._label_prompt_shown = False self._label_urls = [] @@ -595,6 +619,127 @@ def _on_batch_created(self, batch) -> None: self._refresh_status_btn.setEnabled(True) self._update_status_label(batch) + # -- Click & Drop batch -------------------------------------------------- + + def _on_create_cd_batch(self, selection) -> None: + """Click & Drop bulk: create + buy in one call (no async polling).""" + valid_rows = [r for r in self._parsed_rows if r.is_valid] + if not valid_rows: + return + + description = tr( + "batch_shipments.confirm_buy_body", + ) + if not confirm_if_production(self, description): + return + + self._create_batch_btn.setEnabled(False) + self._label_prompt_shown = False + self._label_urls = [] + self._export_sheet_btn.setEnabled(False) + + from_rec = self._address_by_id.get(self._from_combo.currentData()) + from_addr = None + if from_rec: + from_addr = { + "fullName": (from_rec.name or from_rec.company or "").strip(), + "companyName": (from_rec.company or "").strip(), + "addressLine1": (from_rec.street1 or "").strip(), + "addressLine2": (from_rec.street2 or "").strip(), + "addressLine3": "", + "city": (from_rec.city or "").strip(), + "county": (from_rec.state or "").strip(), + "postcode": (from_rec.zip or "").strip(), + "countryCode": to_alpha3((from_rec.country or "GB").upper()), + } + + service_code = selection.service + self._pending_task = run_async( + lambda: bulk_buy_click_drop( + rows=valid_rows, + service_code=service_code, + from_address=from_addr, + ), + self, + ) + self._pending_task.succeeded.connect(self._on_cd_batch_complete) + self._pending_task.failed.connect( + lambda exc: ( + self._update_create_enabled(), + mark_session_friction(), + QMessageBox.critical( + self, tr("common.error"), + tr("batch_shipments.create_failed_body", error=format_api_error(exc)), + ), + ) + ) + + def _on_cd_batch_complete(self, result) -> None: + self._update_create_enabled() + from app.core.client import client_manager + mode = client_manager.active_mode + + label_paths: list[str] = [] + for order in result.created: + to_str = "" + save_click_drop_locally(order, mode, to_address=to_str) + if order.label_pdf_path: + label_paths.append(order.label_pdf_path) + if order.tracking_number: + self._track_cd_order(order.tracking_number, mode) + + self._label_urls = label_paths + self._export_sheet_btn.setEnabled(bool(label_paths)) + self._generate_labels_btn.setEnabled(bool(label_paths)) + + created = len(result.created) + failed = len(result.failed) + status = tr( + "batch_shipments.status_label", + batch_id=f"cd-bulk", + state="purchased", + num_shipments=created, + ) + if failed: + errors = [] + for fo in result.failed: + msgs = [e.get("message", str(e)) for e in fo.get("errors", [])] + errors.append("; ".join(msgs) if msgs else str(fo)) + status += "\n" + "\n".join(errors[:10]) + mark_session_friction() + + self._status_label.setText(status) + self._buy_batch_btn.setEnabled(False) + self._refresh_status_btn.setEnabled(False) + + if not failed: + QMessageBox.information( + self, tr("batch_shipments.purchased_title"), + tr("batch_shipments.purchased_body"), + ) + note_successful_shipment() + schedule_review_prompt(self) + else: + QMessageBox.warning( + self, tr("batch_shipments.purchase_problems_title"), + tr("batch_shipments.purchase_problems_body", + details=f"{created} created, {failed} failed"), + ) + + def _track_cd_order(self, tracking_code: str, mode: str | None) -> None: + from app.services.tracking import create_tracker, save_tracker_locally + + def _do_track(): + tracker = create_tracker(tracking_code, carrier="RoyalMail") + save_tracker_locally(tracker, mode) + + task = run_async(_do_track, self) + task.failed.connect( + lambda exc: logger.warning( + "Could not create tracker for CD batch %s: %s", tracking_code, exc + ) + ) + def _on_refresh_status(self) -> None: if not self._current_batch: return diff --git a/app/ui/views/create_shipment_view.py b/app/ui/views/create_shipment_view.py index 561a74a..2f64740 100644 --- a/app/ui/views/create_shipment_view.py +++ b/app/ui/views/create_shipment_view.py @@ -1,5 +1,6 @@ """Create a shipment, shop rates, buy a label, and save/open it.""" +import logging from functools import partial import requests @@ -8,6 +9,7 @@ from PySide6.QtWidgets import ( QCheckBox, QComboBox, + QCompleter, QDoubleSpinBox, QFileDialog, QFormLayout, @@ -36,7 +38,14 @@ from app.core.errors import carrier_messages, format_api_error from app.core.settings import load_settings, save_settings from app.i18n import tr -from app.services.addresses import address_choice_label, list_addresses +from app.services.addresses import ( + AddressRecord, + AddressVerificationError, + address_choice_label, + list_addresses, + save_address_locally, + verify_address, +) from app.services.carriers import carriers_present_in, for_carrier from app.services.formatting import display_carrier, humanize_code from app.services import rates as rate_rules @@ -55,6 +64,7 @@ fetch_services as fetch_cd_services, save_click_drop_locally, ) +from app.core.countries import to_alpha3 from app.services.shipments import ( buy_shipment, create_rate_quote, @@ -71,6 +81,8 @@ from app.ui.widgets.purchase_confirm import confirm_if_production from app.ui.widgets.review_nudge import schedule_review_prompt +logger = logging.getLogger(__name__) + # Carrier & service | Rate | Est. days | Buy. Rates are shown in a QTreeWidget # grouped by carrier: the carrier is a top-level (header) row and each service # is a child under it, so column 0 carries the carrier name on a header row and @@ -100,16 +112,33 @@ } +_NEW_RECIPIENT = "__new__" + + def _narrowable_combo() -> QComboBox: - """A combo whose longest entry does not set the page's minimum width. + """A filterable combo whose longest entry does not set the page's width. - An address choice reads "Label — street, city, state", and Qt sizes a combo - to its longest entry by default, so one long saved address widened the whole - page. The full text is still shown in the open list. + Editable with a substring-matching completer so the user can type to narrow + the dropdown. Selecting from the popup commits the choice; if focus leaves + without a selection the display reverts to the previously chosen item. """ combo = QComboBox() combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) combo.setMinimumContentsLength(16) + combo.setEditable(True) + combo.setInsertPolicy(QComboBox.InsertPolicy.NoInsert) + completer = combo.completer() + if completer is not None: + completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) + completer.setFilterMode(Qt.MatchFlag.MatchContains) + completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) + le = combo.lineEdit() + if le: + def _restore(c=combo): + idx = c.currentIndex() + if idx >= 0: + c.setEditText(c.itemText(idx)) + le.editingFinished.connect(_restore) return combo @@ -571,14 +600,17 @@ def _build_form_group(self) -> QGroupBox: self._from_combo = _narrowable_combo() self._to_combo = _narrowable_combo() - # Shown while no recipient is chosen, which is how a new shipment starts - # (see refresh_address_choices). - self._to_combo.setPlaceholderText(tr("create_shipment.to_placeholder")) + le = self._to_combo.lineEdit() + if le: + le.setPlaceholderText(tr("create_shipment.to_placeholder")) self._from_combo.currentIndexChanged.connect(self._update_customs_visibility) self._to_combo.currentIndexChanged.connect(self._update_customs_visibility) + self._to_combo.currentIndexChanged.connect(self._on_to_combo_changed) refresh_btn = QPushButton(tr("create_shipment.reload_button")) refresh_btn.clicked.connect(self.refresh_address_choices) + self._inline_recipient_widget = self._build_inline_recipient_form() + # From and To on lines of their own. Side by side, with the reload # button, they needed 1,146px in Tamil. self._full_address_widget = QWidget() @@ -588,7 +620,8 @@ def _build_form_group(self) -> QGroupBox: addr_grid.addWidget(self._from_combo, 0, 1) addr_grid.addWidget(QLabel(tr("create_shipment.to_label")), 1, 0) addr_grid.addWidget(self._to_combo, 1, 1) - addr_grid.addWidget(refresh_btn, 2, 1, alignment=Qt.AlignmentFlag.AlignLeft) + addr_grid.addWidget(self._inline_recipient_widget, 2, 0, 1, 2) + addr_grid.addWidget(refresh_btn, 3, 1, alignment=Qt.AlignmentFlag.AlignLeft) addr_grid.setColumnStretch(1, 1) mode_row = self._build_address_mode_row() @@ -750,6 +783,46 @@ def _build_address_mode_row(self) -> QVBoxLayout: row.addWidget(self._mode_zip_radio) return row + def _build_inline_recipient_form(self) -> QWidget: + """Address fields for a new recipient entered directly on this page.""" + widget = QWidget() + widget.setVisible(False) + form = QFormLayout(widget) + form.setContentsMargins(8, 4, 0, 4) + form.setRowWrapPolicy(QFormLayout.RowWrapPolicy.WrapLongRows) + + self._inline_name = QLineEdit() + self._inline_company = QLineEdit() + self._inline_street1 = QLineEdit() + self._inline_street2 = QLineEdit() + self._inline_city = QLineEdit() + self._inline_state = QLineEdit() + self._inline_zip = QLineEdit() + self._inline_country = self._country_combo() + self._inline_phone = QLineEdit() + self._inline_email = QLineEdit() + + form.addRow(tr("address_book.name_field"), self._inline_name) + form.addRow(tr("address_book.company_field"), self._inline_company) + form.addRow(tr("address_book.street1_field"), self._inline_street1) + form.addRow(tr("address_book.street2_field"), self._inline_street2) + form.addRow(tr("address_book.city_field"), self._inline_city) + form.addRow(tr("address_book.state_field"), self._inline_state) + form.addRow(tr("address_book.zip_field"), self._inline_zip) + form.addRow(tr("address_book.country_field"), self._inline_country) + form.addRow(tr("address_book.phone_field"), self._inline_phone) + form.addRow(tr("address_book.email_field"), self._inline_email) + + self._save_to_book_cb = QCheckBox(tr("create_shipment.save_to_address_book")) + self._save_to_book_cb.setChecked(True) + form.addRow("", self._save_to_book_cb) + + return widget + + def _on_to_combo_changed(self) -> None: + is_new = self._to_combo.currentData() == _NEW_RECIPIENT + self._inline_recipient_widget.setVisible(is_new) + def _build_zip_row(self) -> QWidget: self._from_zip_input = QLineEdit() self._from_zip_input.setPlaceholderText(tr("create_shipment.zip_placeholder")) @@ -1198,9 +1271,32 @@ def _on_remove_customs_item(self, button: QPushButton) -> None: self._invalidate_rates() return + def _get_to_record(self) -> AddressRecord | None: + """The recipient, from the address book or the inline form.""" + to_id = self._to_combo.currentData() + if to_id == _NEW_RECIPIENT: + return AddressRecord( + id="", + mode="", + label=None, + name=self._inline_name.text().strip() or None, + company=self._inline_company.text().strip() or None, + street1=self._inline_street1.text().strip() or None, + street2=self._inline_street2.text().strip() or None, + city=self._inline_city.text().strip() or None, + state=self._inline_state.text().strip() or None, + zip=self._inline_zip.text().strip() or None, + country=self._inline_country.currentData() or None, + phone=self._inline_phone.text().strip() or None, + email=self._inline_email.text().strip() or None, + verified=False, + is_favorite=False, + ) + return self._address_by_id.get(to_id) + def _is_international(self) -> bool: from_rec = self._address_by_id.get(self._from_combo.currentData()) - to_rec = self._address_by_id.get(self._to_combo.currentData()) + to_rec = self._get_to_record() return customs.is_international( getattr(from_rec, "country", None), getattr(to_rec, "country", None) ) @@ -1829,6 +1925,9 @@ def refresh_address_choices(self) -> None: combo.clear() for rec in records: combo.addItem(address_choice_label(rec), rec.id) + self._to_combo.addItem( + tr("create_shipment.new_recipient_option"), _NEW_RECIPIENT + ) self._from_combo.setCurrentIndex( max(self._from_combo.findData(previous_from), 0) if records else -1 ) @@ -1836,6 +1935,7 @@ def refresh_address_choices(self) -> None: self._to_combo.setCurrentIndex(self._to_combo.findData(previous_to)) for combo in (self._from_combo, self._to_combo): combo.blockSignals(False) + self._on_to_combo_changed() self._update_customs_visibility() if (self._from_combo.currentData(), self._to_combo.currentData()) != ( previous_from, previous_to @@ -1913,6 +2013,14 @@ def _connect_rate_invalidation(self) -> None: line.textChanged.connect(self._invalidate_rates) self._customs_certify_checkbox.toggled.connect(self._invalidate_rates) self._mode_full_radio.toggled.connect(self._invalidate_rates) + for inline_line in ( + self._inline_name, self._inline_company, self._inline_street1, + self._inline_street2, self._inline_city, self._inline_state, + self._inline_zip, self._inline_phone, self._inline_email, + ): + inline_line.textChanged.connect(self._invalidate_rates) + self._inline_country.currentIndexChanged.connect(self._invalidate_rates) + self._inline_country.currentIndexChanged.connect(self._update_customs_visibility) def _begin_rating(self) -> int: """Start a rating request and return the generation its reply must @@ -1949,6 +2057,7 @@ def _on_get_rates_clicked(self) -> None: from_id = self._from_combo.currentData() to_id = self._to_combo.currentData() + inline = to_id == _NEW_RECIPIENT if self._from_combo.count() < 2 or not from_id: QMessageBox.warning( self, @@ -1957,9 +2066,6 @@ def _on_get_rates_clicked(self) -> None: ) return if not to_id: - # There are addresses to choose from; the user has not chosen one. - # "Verify at least two addresses first" would send them to the - # Address Book for nothing. QMessageBox.warning( self, tr("create_shipment.missing_addresses_title"), @@ -1967,7 +2073,17 @@ def _on_get_rates_clicked(self) -> None: ) self._to_combo.setFocus() return - if from_id == to_id: + + to_rec = self._get_to_record() + if inline: + if not (to_rec and to_rec.street1 and to_rec.city): + QMessageBox.warning( + self, + tr("create_shipment.missing_addresses_title"), + tr("create_shipment.inline_missing_street_city"), + ) + return + elif from_id == to_id: QMessageBox.warning( self, tr("create_shipment.same_address_title"), @@ -1979,14 +2095,9 @@ def _on_get_rates_clicked(self) -> None: customs_info = None if self._is_international(): from_rec = self._address_by_id.get(from_id) - to_rec = self._address_by_id.get(to_id) if not (from_rec.name or from_rec.company or "").strip() or not ( to_rec.name or to_rec.company or "" ).strip(): - # Carriers require a name or company on both addresses for the - # customs declaration. EasyPost's error for this is buried in - # a generic 400 ("malformed syntax") unless the detailed - # errors list is surfaced — see app/core/errors.py. QMessageBox.warning( self, tr("create_shipment.missing_name_title"), @@ -1994,11 +2105,6 @@ def _on_get_rates_clicked(self) -> None: ) return if not (from_rec.phone or "").strip() or not (to_rec.phone or "").strip(): - # Carriers require a phone number on both addresses for an - # international label. USPS reports a useless generic 400 when - # it's missing rather than a clear validation error (DHL/FedEx - # do report it clearly) — catch it here instead of letting the - # user hit that opaque error at buy time. QMessageBox.warning( self, tr("create_shipment.missing_phone_title"), @@ -2019,13 +2125,27 @@ def _on_get_rates_clicked(self) -> None: package_data = self._package_combo.currentData() params = dict( - to_address_id=to_id, from_address_id=from_id, weight=self._weight_oz(), reference=self._reference_input.text().strip(), customs_info=customs_info, delivery_confirmation=self._signature_combo.currentData(), ) + if inline: + params["to_address"] = { + "name": to_rec.name or None, + "company": to_rec.company or None, + "street1": to_rec.street1, + "street2": to_rec.street2 or None, + "city": to_rec.city, + "state": to_rec.state or None, + "zip": to_rec.zip or None, + "country": to_rec.country or "US", + "phone": to_rec.phone or None, + "email": to_rec.email or None, + } + else: + params["to_address_id"] = to_id if isinstance(package_data, tuple) and package_data[0] == "predefined": params["predefined_package"] = package_data[1].name else: @@ -2146,7 +2266,7 @@ def _fetch_click_drop_rates(self) -> None: country = (self._to_country_combo.currentData() or "GB").upper() postcode = self._to_zip_input.text().strip() else: - to_rec = self._address_by_id.get(self._to_combo.currentData()) + to_rec = self._get_to_record() if not to_rec: return country = (to_rec.country or "GB").upper() @@ -2200,7 +2320,7 @@ def _buy_click_drop(self, rate) -> None: self._set_purchase_in_flight(False) return - to_rec = self._address_by_id.get(self._to_combo.currentData()) + to_rec = self._get_to_record() from_rec = self._address_by_id.get(self._from_combo.currentData()) if not to_rec: self._set_purchase_in_flight(False) @@ -2216,21 +2336,22 @@ def _buy_click_drop(self, rate) -> None: "city": (to_rec.city or "").strip(), "county": (to_rec.state or "").strip(), "postcode": (to_rec.zip or "").strip(), - "countryCode": (to_rec.country or "GB").upper(), + "countryCode": to_alpha3((to_rec.country or "GB").upper()), "phoneNumber": (to_rec.phone or "").strip(), "emailAddress": (to_rec.email or "").strip(), } weight_g = int(self._weight_oz() * 28.3495) if self._weight_oz() else 0 - packages = [{"weightInGrams": weight_g, "packageFormatIdentifier": "Parcel"}] + pkg_format = getattr(rate, "package_format", "") or "Parcel" + packages = [{"weightInGrams": weight_g, "packageFormatIdentifier": pkg_format}] length = self._length_in() width = self._width_in() height = self._height_in() if length and width and height: - packages[0]["heightInCm"] = round(height * 2.54, 1) - packages[0]["widthInCm"] = round(width * 2.54, 1) - packages[0]["depthInCm"] = round(length * 2.54, 1) + packages[0]["heightInMms"] = round(height * 25.4) + packages[0]["widthInMms"] = round(width * 25.4) + packages[0]["depthInMms"] = round(length * 25.4) reference = self._reference_input.text().strip() mode = client_manager.active_mode @@ -2269,6 +2390,9 @@ def _on_cd_bought( self._result_label.setVisible(bool(tracking_code)) self._track_btn.setVisible(bool(tracking_code)) + if tracking_code: + self._track_cd_shipment(tracking_code, mode) + if order.label_pdf_path: self._open_label_btn.setEnabled(True) self._save_label_btn.setEnabled(True) @@ -2287,9 +2411,62 @@ def _on_cd_bought( self._result_group.setVisible(True) self._reveal_result() + self._maybe_save_inline_recipient() note_successful_shipment() schedule_review_prompt(self) + def _maybe_save_inline_recipient(self) -> None: + """If an inline recipient was entered and save-to-address-book is + ticked, verify + save it in the background after a purchase.""" + if self._to_combo.currentData() != _NEW_RECIPIENT: + return + if not self._save_to_book_cb.isChecked(): + return + rec = self._get_to_record() + if not rec or not rec.street1 or not rec.city: + return + + def _do_save(): + try: + addr = verify_address( + name=rec.name or "", + company=rec.company or "", + street1=rec.street1, + street2=rec.street2 or "", + city=rec.city, + state=rec.state or "", + zip=rec.zip or "", + country=rec.country or "US", + phone=rec.phone or "", + email=rec.email or "", + ) + save_address_locally(addr, label=rec.name or rec.company, verified=True) + except AddressVerificationError as exc: + save_address_locally(exc.address, label=rec.name or rec.company, verified=False) + except Exception: + logger.warning("Could not save inline recipient to address book", exc_info=True) + + task = run_async(_do_save, self) + task.succeeded.connect(lambda _: self.refresh_address_choices()) + + def _track_cd_shipment(self, tracking_code: str, mode: str | None) -> None: + """Create an EasyPost tracker for a Click & Drop shipment. + + EasyPost can track any Royal Mail parcel by tracking number, so + Click & Drop purchases appear on the Tracking page alongside + EasyPost ones. Best effort — the label is already bought. + """ + from app.services.tracking import create_tracker, save_tracker_locally + + def _do_track(): + tracker = create_tracker(tracking_code, carrier="RoyalMail") + save_tracker_locally(tracker, mode) + + task = run_async(_do_track, self) + task.failed.connect( + lambda exc: logger.warning("Could not create tracker for CD %s: %s", tracking_code, exc) + ) + # ── Currency / carrier helpers ─────────────────────────────────────── def _sender_currency(self) -> str | None: @@ -2429,9 +2606,8 @@ def _on_bought(self, shipment, mode: str | None = None) -> None: self._result_group.setVisible(True) self._reveal_result() - # A bought label is the moment of satisfaction, so it is where the review - # prompt belongs. Both calls are no-ops on builds with no storefront, and - # every other gate is applied inside them. + self._maybe_save_inline_recipient() + note_successful_shipment() schedule_review_prompt(self) diff --git a/app/ui/views/history_view.py b/app/ui/views/history_view.py index 099b121..7a5d738 100644 --- a/app/ui/views/history_view.py +++ b/app/ui/views/history_view.py @@ -32,6 +32,10 @@ is_pending, validate_amount, ) +from app.services.click_drop import ( + create_click_drop_manifest, + void_click_drop_order, +) from app.services.manifests import create_manifest, save_manifest_locally from app.services.shipments import ( is_refund_pending, @@ -174,19 +178,26 @@ def refresh_table(self) -> None: open_btn.clicked.connect(partial(open_label, rec.label_url)) actions_layout.addWidget(open_btn) - insure_btn = QPushButton( - tr("history.insure_button") - if not rec.insured_amount - else tr("history.update_insurance_button") - ) - insure_btn.clicked.connect(partial(self._on_insure_clicked, rec.id)) - actions_layout.addWidget(insure_btn) - - if not rec.refund_status: + is_cd = rec.id.startswith("cd_") if rec.id else False + + if not is_cd: + insure_btn = QPushButton( + tr("history.insure_button") + if not rec.insured_amount + else tr("history.update_insurance_button") + ) + insure_btn.clicked.connect(partial(self._on_insure_clicked, rec.id)) + actions_layout.addWidget(insure_btn) + + if is_cd and not rec.refund_status: + void_btn = QPushButton(tr("history.void_order_button")) + void_btn.clicked.connect(partial(self._on_void_cd_clicked, rec.id)) + actions_layout.addWidget(void_btn) + elif not is_cd and not rec.refund_status: refund_btn = QPushButton(tr("history.request_refund_button")) refund_btn.clicked.connect(partial(self._on_refund_clicked, rec.id)) actions_layout.addWidget(refund_btn) - elif is_refund_pending(rec.refund_status): + elif not is_cd and is_refund_pending(rec.refund_status): check_btn = QPushButton(tr("history.check_refund_status_button")) check_btn.clicked.connect(partial(self._on_check_refund_clicked, rec.id)) actions_layout.addWidget(check_btn) @@ -278,10 +289,56 @@ def _on_refund_status_checked(self, status) -> None: self, tr("history.refund_status_title"), tr("history.refund_status_body", status=status) ) + def _on_void_cd_clicked(self, shipment_id: str) -> None: + if not confirm_if_production( + self, tr("history.confirm_void_order") + ): + return + mark_session_friction() + order_id = int(shipment_id.removeprefix("cd_")) + self._pending_task = run_async(lambda: void_click_drop_order(order_id), self) + self._pending_task.succeeded.connect(lambda _: self._on_void_complete()) + self._pending_task.failed.connect( + lambda exc: QMessageBox.critical( + self, tr("history.error_title"), tr("history.void_failed", error=format_api_error(exc)) + ) + ) + + def _on_void_complete(self) -> None: + self.refresh_table() + QMessageBox.information( + self, + tr("history.void_complete_title"), + tr("history.void_complete_body"), + ) + def _on_create_manifest(self) -> None: rows = sorted({idx.row() for idx in self._table.selectionModel().selectedRows()}) selected = [self._records[r] for r in rows if r < len(self._records)] - eligible = [s for s in selected if s.tracking_code and not s.scan_form_id] + + cd_eligible = [ + s for s in selected + if (s.id or "").startswith("cd_") and s.tracking_code and not s.scan_form_id + ] + ep_eligible = [ + s for s in selected + if s.tracking_code and not s.scan_form_id + and not (s.id or "").startswith("cd_") + ] + + if cd_eligible and ep_eligible: + QMessageBox.warning( + self, + tr("history.manifest_created_title"), + tr("history.manifest_mixed_carrier"), + ) + return + + if cd_eligible: + self._on_create_cd_manifest() + return + + eligible = ep_eligible if not eligible: QMessageBox.information( self, @@ -310,6 +367,35 @@ def _on_create_manifest(self) -> None: ) ) + def _on_create_cd_manifest(self) -> None: + self._pending_task = run_async(create_click_drop_manifest, self) + self._pending_task.succeeded.connect(self._on_cd_manifest_created) + self._pending_task.failed.connect( + lambda exc: QMessageBox.critical( + self, + tr("history.manifest_created_title"), + tr("history.manifest_failed_body", error=format_api_error(exc)), + ) + ) + + def _on_cd_manifest_created(self, result) -> None: + self.refresh_table() + if result.pdf_path: + reply = QMessageBox.question( + self, + tr("history.manifest_created_title"), + tr("history.cd_manifest_created_body"), + QMessageBox.StandardButton.Open | QMessageBox.StandardButton.Close, + ) + if reply == QMessageBox.StandardButton.Open: + open_label(result.pdf_path) + else: + QMessageBox.information( + self, + tr("history.manifest_created_title"), + tr("history.cd_manifest_pending_body"), + ) + def _on_manifest_created(self, result, shipment_ids: list[str]) -> None: save_manifest_locally(result.scan_form, shipment_ids, result.local_pdf_path) self.refresh_table() diff --git a/store_assets/RELEASE-NOTES-1.5.0.md b/store_assets/RELEASE-NOTES-1.5.0.md new file mode 100644 index 0000000..ed2243d --- /dev/null +++ b/store_assets/RELEASE-NOTES-1.5.0.md @@ -0,0 +1,47 @@ +# Easy-Post Desktop — release notes 1.5.0 + +Covers everything since 1.3.2, which was the last published version on both +stores. The version jump to 1.5.0 is deliberate: 1.4.0 was submitted to the Mac +App Store but not to Partner Center, and the two stores now share a version. + +## What is in 1.5.0 for a customer + +**Royal Mail Click & Drop — ship with Royal Mail directly (#92).** A second +carrier path alongside EasyPost. Enter a Click & Drop API key in Settings, and +Royal Mail services appear in the rates tree next to EasyPost rates. The same +buy-and-track flow as EasyPost: one-click label purchase, local PDF save, +tracking number in History. + +**Carrier manifesting / scan forms (#88, #90).** Generate end-of-day manifests +for your carriers, a requirement for some collection services. Royal Mail +manifest PDFs that arrived with formatting errors are now regenerated locally +with the correct layout. + +**Smart dropdown filtering.** All address dropdowns now support type-to-filter +with substring matching — start typing any part of a name, company or address +and the list narrows in real time. Works across Create Shipment and Batch Import. + +**Inline recipient entry.** Ship to someone without adding them to the address +book first. Select "Enter new recipient…" at the bottom of the To dropdown and +fill in the address fields inline. A "Save to address book" checkbox +(on by default) saves the address automatically after a successful purchase. + +**Multiple macOS stability fixes (#83–87).** API key fields, focus behaviour and +entitlements are corrected for macOS Tahoe. These only affect the Mac App Store +build. + +## Copy for the store listings + +English master. The macOS-specific fixes are review compliance, not customer +features, so the copy is the same on both stores. + +> Ship with Royal Mail directly through Click & Drop, alongside your EasyPost +> carriers. Enter a Click & Drop API key in Settings and Royal Mail services +> appear in the rates tree. +> +> • Generate end-of-day carrier manifests (scan forms) from the new Manifests +> page, and print corrected Royal Mail manifest PDFs. +> • Type-to-filter dropdowns with substring matching across the app. +> • Enter a new recipient directly on the Create Shipment page — no address +> book entry required. +> • Multiple macOS stability improvements. From ff0260a5844108a6a9f3befd6068d88553857135 Mon Sep 17 00:00:00 2001 From: Spencer Fields <58378262+sgf36@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:46:26 +0100 Subject: [PATCH 3/4] Bump version to 1.6.0 1.5.0 is already live on the Microsoft Store, so all three channels (Partner Center, Mac App Store, direct download) advance to 1.6.0. Co-Authored-By: Claude Opus 4.6 --- app/config.py | 2 +- packaging/msix/AppxManifest.xml | 2 +- site/ar/download.html | 6 +++--- site/bn/download.html | 6 +++--- site/de/download.html | 6 +++--- site/download.html | 6 +++--- site/es/download.html | 6 +++--- site/fr/download.html | 6 +++--- site/hi/download.html | 6 +++--- site/id/download.html | 6 +++--- site/ja/download.html | 6 +++--- site/mr/download.html | 6 +++--- site/pt/download.html | 6 +++--- site/ru/download.html | 6 +++--- site/sv/download.html | 6 +++--- site/te/download.html | 6 +++--- site/ur/download.html | 6 +++--- site/zh/download.html | 6 +++--- .../{RELEASE-NOTES-1.5.0.md => RELEASE-NOTES-1.6.0.md} | 9 +++++---- 19 files changed, 55 insertions(+), 54 deletions(-) rename store_assets/{RELEASE-NOTES-1.5.0.md => RELEASE-NOTES-1.6.0.md} (87%) diff --git a/app/config.py b/app/config.py index 1198d9f..94300c7 100644 --- a/app/config.py +++ b/app/config.py @@ -13,7 +13,7 @@ # (app/core/update_check.py) compares this against the latest GitHub release # tag to decide whether to prompt the user to update. Keep it in step with the # release tag and packaging/msix/AppxManifest.xml on every release. -APP_VERSION = "1.5.0" +APP_VERSION = "1.6.0" ICON_PATH = Path(__file__).parent / "resources" / "icons" / "app_icon.png" diff --git a/packaging/msix/AppxManifest.xml b/packaging/msix/AppxManifest.xml index a2319a8..9bd3b0f 100644 --- a/packaging/msix/AppxManifest.xml +++ b/packaging/msix/AppxManifest.xml @@ -9,7 +9,7 @@ diff --git a/site/ar/download.html b/site/ar/download.html index 1a0924b..9ef9b48 100644 --- a/site/ar/download.html +++ b/site/ar/download.html @@ -51,7 +51,7 @@

تنزيل

-

الإصدار 1.3.1

+

الإصدار 1.6.0

لأنظمة Windows و macOS. التثبيت مجاني — ومفتاح الترخيص يفتح الاستخدام الإنتاجي. أما نسختا Microsoft Store و Mac App Store فتفتحانه داخل التطبيق نفسه.

@@ -65,7 +65,7 @@

الإصدار 1.3.1

Windows 10 و11

64 بت · 86 ميغابايت

فُك الضغط في أي مكان، ثم شغّل EasyPostDesktop.exe

- تنزيل لنظام Windows + تنزيل لنظام Windows
@@ -73,7 +73,7 @@

Windows 10 و11

macOS على معالجات Apple silicon

Apple silicon · 82 ميغابايت

موثّقة من Apple · تُفتح بلا أي تحذيرات

- تنزيل لنظام macOS + تنزيل لنظام macOS
diff --git a/site/bn/download.html b/site/bn/download.html index 37f5b3d..4378986 100644 --- a/site/bn/download.html +++ b/site/bn/download.html @@ -51,7 +51,7 @@

ডাউনলোড

-

সংস্করণ ১.৩.১

+

সংস্করণ ১.৬.০

Windows ও macOS। বিনামূল্যে ইনস্টল করুন — একটি লাইসেন্স কী প্রোডাকশন ব্যবহার আনলক করে। Microsoft Store এবং Mac App Store সংস্করণগুলি এর পরিবর্তে অ্যাপের মধ্যেই এটি আনলক করে।

@@ -65,7 +65,7 @@

সংস্করণ ১.৩.১

Windows 10 ও 11

৬৪-বিট · ৮৬ MB

যেকোনো জায়গায় আনজিপ করুন, তারপর EasyPostDesktop.exe চালান

- Windows-এর জন্য ডাউনলোড করুন + Windows-এর জন্য ডাউনলোড করুন
@@ -73,7 +73,7 @@

Windows 10 ও 11

Apple silicon-এ macOS

Apple silicon · 82 MB

Apple দ্বারা নোটারাইজড · কোনো সতর্কবার্তা ছাড়াই খোলে

- macOS-এর জন্য ডাউনলোড করুন + macOS-এর জন্য ডাউনলোড করুন
diff --git a/site/de/download.html b/site/de/download.html index 9629d7c..3d33b0e 100644 --- a/site/de/download.html +++ b/site/de/download.html @@ -51,7 +51,7 @@

Download

-

Version 1.3.1

+

Version 1.6.0

Windows und macOS. Kostenlose Installation – ein Lizenzschlüssel schaltet die produktive Nutzung frei. Bei den Versionen aus dem Microsoft Store und dem Mac App Store erfolgt die Freischaltung stattdessen direkt in der App.

@@ -65,7 +65,7 @@

Version 1.3.1

Windows 10 & 11

64-Bit · 86 MB

Entpacken Sie die Datei an einem beliebigen Ort und führen Sie dann EasyPostDesktop.exe aus

- Für Windows herunterladen + Für Windows herunterladen
@@ -73,7 +73,7 @@

Windows 10 & 11

macOS auf Apple Silicon

Apple Silicon · 82 MB

Von Apple notarisiert · öffnet ohne Warnungen

- Für macOS herunterladen + Für macOS herunterladen
diff --git a/site/download.html b/site/download.html index 7c2dfac..c564fdd 100644 --- a/site/download.html +++ b/site/download.html @@ -55,7 +55,7 @@

Download

-

Version 1.3.1

+

Version 1.6.0

Windows and macOS. Free to install — a licence key unlocks production use. The Microsoft Store and Mac App Store versions unlock it in the app instead.

@@ -69,7 +69,7 @@

Version 1.3.1

Windows 10 & 11

64-bit · 86 MB

Unzip anywhere, then run EasyPostDesktop.exe

- Download for Windows + Download for Windows
@@ -77,7 +77,7 @@

Windows 10 & 11

macOS on Apple silicon

Apple silicon · 82 MB

Notarized by Apple · opens without warnings

- Download for macOS + Download for macOS
diff --git a/site/es/download.html b/site/es/download.html index 1679b68..0a9e815 100644 --- a/site/es/download.html +++ b/site/es/download.html @@ -51,7 +51,7 @@

Descargar

-

Versión 1.3.1

+

Versión 1.6.0

Windows y macOS. Instalación gratuita — una clave de licencia desbloquea el uso en producción. Las versiones de Microsoft Store y Mac App Store lo desbloquean directamente en la aplicación.

@@ -65,7 +65,7 @@

Versión 1.3.1

Windows 10 y 11

64 bits · 86 MB

Descomprima en cualquier carpeta y ejecute EasyPostDesktop.exe

- Descargar para Windows + Descargar para Windows
@@ -73,7 +73,7 @@

Windows 10 y 11

macOS en Apple silicon

Apple silicon · 82 MB

Notarizado por Apple · se abre sin advertencias

- Descargar para macOS + Descargar para macOS
diff --git a/site/fr/download.html b/site/fr/download.html index dc7f020..36ea0bb 100644 --- a/site/fr/download.html +++ b/site/fr/download.html @@ -51,7 +51,7 @@

Télécharger

-

Version 1.3.1

+

Version 1.6.0

Windows et macOS. Installation gratuite — une clé de licence débloque l'usage en production. Les versions du Microsoft Store et du Mac App Store le débloquent directement dans l'application.

@@ -65,7 +65,7 @@

Version 1.3.1

Windows 10 et 11

64 bits · 86 Mo

Décompressez où vous le souhaitez, puis lancez EasyPostDesktop.exe

- Télécharger pour Windows + Télécharger pour Windows
@@ -73,7 +73,7 @@

Windows 10 et 11

macOS sur puce Apple

Puce Apple · 82 Mo

Notarisé par Apple · s'ouvre sans avertissement

- Télécharger pour macOS + Télécharger pour macOS
diff --git a/site/hi/download.html b/site/hi/download.html index 377e68f..b60c751 100644 --- a/site/hi/download.html +++ b/site/hi/download.html @@ -51,7 +51,7 @@

डाउनलोड

-

संस्करण 1.3.1

+

संस्करण 1.6.0

Windows और macOS। इंस्टॉल करना निःशुल्क है — एक लाइसेंस कुंजी उत्पादन उपयोग को अनलॉक करती है। Microsoft Store और Mac App Store संस्करण इसे इसके बजाय ऐप के भीतर अनलॉक करते हैं।

@@ -65,7 +65,7 @@

संस्करण 1.3.1

Windows 10 और 11

64-बिट · 86 MB

कहीं भी अनज़िप करें, फिर EasyPostDesktop.exe चलाएँ

- Windows के लिए डाउनलोड करें + Windows के लिए डाउनलोड करें
@@ -73,7 +73,7 @@

Windows 10 और 11

Apple silicon पर macOS

Apple silicon · 82 MB

Apple द्वारा सत्यापित (notarized) · बिना किसी चेतावनी के खुलता है

- macOS के लिए डाउनलोड करें + macOS के लिए डाउनलोड करें
diff --git a/site/id/download.html b/site/id/download.html index 68384dd..7eb62ee 100644 --- a/site/id/download.html +++ b/site/id/download.html @@ -51,7 +51,7 @@

Unduh

-

Versi 1.3.1

+

Versi 1.6.0

Windows dan macOS. Gratis dipasang — kunci lisensi membuka penggunaan produksi. Versi Microsoft Store dan Mac App Store membukanya langsung di dalam aplikasi.

@@ -65,7 +65,7 @@

Versi 1.3.1

Windows 10 & 11

64-bit · 86 MB

Ekstrak ke mana saja, lalu jalankan EasyPostDesktop.exe

- Unduh untuk Windows + Unduh untuk Windows
@@ -73,7 +73,7 @@

Windows 10 & 11

macOS pada Apple silicon

Apple silicon · 82 MB

Dinotarisasi oleh Apple · terbuka tanpa peringatan

- Unduh untuk macOS + Unduh untuk macOS
diff --git a/site/ja/download.html b/site/ja/download.html index 6f6d467..2fda00e 100644 --- a/site/ja/download.html +++ b/site/ja/download.html @@ -51,7 +51,7 @@

ダウンロード

-

バージョン 1.3.1

+

バージョン 1.6.0

Windows と macOS に対応しています。インストールは無料で、ライセンスキーにより本番利用が解放されます。Microsoft Store 版と Mac App Store 版はアプリ内で解放される仕組みです。

@@ -65,7 +65,7 @@

バージョン 1.3.1

Windows 10 & 11

64ビット・86 MB

任意の場所に解凍し、EasyPostDesktop.exe を実行してください

- Windows 用をダウンロード + Windows 用をダウンロード
@@ -73,7 +73,7 @@

Windows 10 & 11

Apple silicon 搭載の macOS

Apple silicon · 82 MB

Apple による公証済み · 警告なしで開きます

- macOS 用をダウンロード + macOS 用をダウンロード
diff --git a/site/mr/download.html b/site/mr/download.html index 85c21e4..878ad53 100644 --- a/site/mr/download.html +++ b/site/mr/download.html @@ -51,7 +51,7 @@

डाउनलोड

-

आवृत्ती 1.3.1

+

आवृत्ती 1.6.0

Windows आणि macOS. विनामूल्य इंस्टॉल करा — लायसन्स की उत्पादन वापर अनलॉक करते. Microsoft Store आणि Mac App Store आवृत्त्या त्याऐवजी अ‍ॅपमध्येच अनलॉक करतात.

@@ -65,7 +65,7 @@

आवृत्ती 1.3.1

Windows 10 आणि 11

64-बिट · 86 MB

कुठेही अनझिप करा, नंतर EasyPostDesktop.exe चालवा

- Windows साठी डाउनलोड करा + Windows साठी डाउनलोड करा
@@ -73,7 +73,7 @@

Windows 10 आणि 11

Apple silicon वर macOS

Apple silicon · 82 MB

Apple कडून नोटराइझ्ड · कोणत्याही चेतावणीशिवाय उघडते

- macOS साठी डाउनलोड करा + macOS साठी डाउनलोड करा
diff --git a/site/pt/download.html b/site/pt/download.html index cbfac7c..4cb6037 100644 --- a/site/pt/download.html +++ b/site/pt/download.html @@ -51,7 +51,7 @@

Transferir

-

Versão 1.3.1

+

Versão 1.6.0

Windows e macOS. Instalação gratuita — uma chave de licença desbloqueia o uso em produção. As versões da Microsoft Store e da Mac App Store desbloqueiam-no diretamente na aplicação.

@@ -65,7 +65,7 @@

Versão 1.3.1

Windows 10 e 11

64 bits · 86 MB

Descompacte em qualquer local e execute o EasyPostDesktop.exe

- Transferir para Windows + Transferir para Windows
@@ -73,7 +73,7 @@

Windows 10 e 11

macOS em Apple silicon

Apple silicon · 82 MB

Notarizado pela Apple · abre sem avisos

- Transferir para macOS + Transferir para macOS
diff --git a/site/ru/download.html b/site/ru/download.html index 6289880..9ad3508 100644 --- a/site/ru/download.html +++ b/site/ru/download.html @@ -51,7 +51,7 @@

Скачать

-

Версия 1.3.1

+

Версия 1.6.0

Windows и macOS. Бесплатная установка — ключ лицензии открывает работу в продуктивном режиме. Версии из Microsoft Store и Mac App Store открывают её прямо в приложении.

@@ -65,7 +65,7 @@

Версия 1.3.1

Windows 10 и 11

64-бит · 86 МБ

Распакуйте архив в любую папку, затем запустите EasyPostDesktop.exe

- Скачать для Windows + Скачать для Windows
@@ -73,7 +73,7 @@

Windows 10 и 11

macOS на Apple silicon

Apple silicon · 82 МБ

Нотариально заверено Apple · открывается без предупреждений

- Скачать для macOS + Скачать для macOS
diff --git a/site/sv/download.html b/site/sv/download.html index a92b927..d081566 100644 --- a/site/sv/download.html +++ b/site/sv/download.html @@ -51,7 +51,7 @@

Ladda ner

-

Version 1.3.1

+

Version 1.6.0

Windows och macOS. Gratis att installera — en licensnyckel låser upp produktionsanvändning. Versionerna från Microsoft Store och Mac App Store låser i stället upp den i appen.

@@ -65,7 +65,7 @@

Version 1.3.1

Windows 10 och 11

64-bitars · 86 MB

Packa upp var som helst, och kör sedan EasyPostDesktop.exe

- Ladda ner för Windows + Ladda ner för Windows
@@ -73,7 +73,7 @@

Windows 10 och 11

macOS för Apple silicon

Apple silicon · 82 MB

Notariserad av Apple · öppnas utan varningar

- Ladda ned för macOS + Ladda ned för macOS
diff --git a/site/te/download.html b/site/te/download.html index f4fce25..44c6533 100644 --- a/site/te/download.html +++ b/site/te/download.html @@ -51,7 +51,7 @@

డౌన్‌లోడ్

-

వెర్షన్ 1.3.1

+

వెర్షన్ 1.6.0

Windows మరియు macOS. ఇన్‌స్టాల్ చేయడం ఉచితం — ఒక లైసెన్స్ కీ ప్రొడక్షన్ ఉపయోగాన్ని అన్‌లాక్ చేస్తుంది. Microsoft Store మరియు Mac App Store వెర్షన్‌లు దీన్ని యాప్‌లోనే అన్‌లాక్ చేస్తాయి.

@@ -65,7 +65,7 @@

వెర్షన్ 1.3.1

Windows 10 & 11

64-బిట్ · 86 MB

ఎక్కడైనా అన్‌జిప్ చేసి, తర్వాత EasyPostDesktop.exe రన్ చేయండి

- Windows కోసం డౌన్‌లోడ్ చేయండి + Windows కోసం డౌన్‌లోడ్ చేయండి
@@ -73,7 +73,7 @@

Windows 10 & 11

Apple సిలికాన్‌పై macOS

Apple సిలికాన్ · 82 MB

Apple ద్వారా నోటరైజ్ చేయబడింది · హెచ్చరికలు లేకుండా తెరుచుకుంటుంది

- macOS కోసం డౌన్‌లోడ్ చేయండి + macOS కోసం డౌన్‌లోడ్ చేయండి
diff --git a/site/ur/download.html b/site/ur/download.html index 14a1b07..d4a4eb0 100644 --- a/site/ur/download.html +++ b/site/ur/download.html @@ -51,7 +51,7 @@

ڈاؤن لوڈ

-

ورژن 1.3.1

+

ورژن 1.6.0

Windows اور macOS۔ انسٹال کرنا مفت ہے — ایک لائسنس کلید پروڈکشن استعمال کو غیر مقفل کرتی ہے۔ Microsoft Store اور Mac App Store کے ورژنز اسے ایپ کے اندر ہی غیر مقفل کر دیتے ہیں۔

@@ -65,7 +65,7 @@

ورژن 1.3.1

Windows 10 اور 11

64-بٹ · 86 MB

کہیں بھی ان زپ کریں، پھر EasyPostDesktop.exe چلائیں

- Windows کے لیے ڈاؤن لوڈ کریں + Windows کے لیے ڈاؤن لوڈ کریں
@@ -73,7 +73,7 @@

Windows 10 اور 11

Apple silicon پر macOS

Apple silicon · 82 MB

Apple کی جانب سے نوٹرائزڈ · بغیر کسی وارننگ کے کھلتا ہے

- macOS کے لیے ڈاؤن لوڈ کریں + macOS کے لیے ڈاؤن لوڈ کریں
diff --git a/site/zh/download.html b/site/zh/download.html index 040cdec..c2b3609 100644 --- a/site/zh/download.html +++ b/site/zh/download.html @@ -51,7 +51,7 @@

下载

-

版本 1.3.1

+

版本 1.6.0

Windows 和 macOS。免费安装——许可证密钥可解锁正式使用。Microsoft Store 和 Mac App Store 版本则在应用内解锁。

@@ -65,7 +65,7 @@

版本 1.3.1

Windows 10 和 11

64 位 · 86 MB

解压到任意位置,然后运行 EasyPostDesktop.exe

- 下载 Windows 版 + 下载 Windows 版
@@ -73,7 +73,7 @@

Windows 10 和 11

适用于 Apple silicon 的 macOS

Apple silicon · 82 MB

已通过 Apple 公证 · 打开时不会出现警告

- 下载 macOS 版 + 下载 macOS 版
diff --git a/store_assets/RELEASE-NOTES-1.5.0.md b/store_assets/RELEASE-NOTES-1.6.0.md similarity index 87% rename from store_assets/RELEASE-NOTES-1.5.0.md rename to store_assets/RELEASE-NOTES-1.6.0.md index ed2243d..1703ccd 100644 --- a/store_assets/RELEASE-NOTES-1.5.0.md +++ b/store_assets/RELEASE-NOTES-1.6.0.md @@ -1,10 +1,11 @@ -# Easy-Post Desktop — release notes 1.5.0 +# Easy-Post Desktop — release notes 1.6.0 Covers everything since 1.3.2, which was the last published version on both -stores. The version jump to 1.5.0 is deliberate: 1.4.0 was submitted to the Mac -App Store but not to Partner Center, and the two stores now share a version. +stores. The version jump to 1.6.0 is deliberate: 1.4.0 was submitted to the Mac +App Store, 1.5.0 went live on the Microsoft Store, and 1.6.0 brings all three +channels (Partner Center, Mac App Store, direct download) back in sync. -## What is in 1.5.0 for a customer +## What is in 1.6.0 for a customer **Royal Mail Click & Drop — ship with Royal Mail directly (#92).** A second carrier path alongside EasyPost. Enter a Click & Drop API key in Settings, and From 5434160a123ad86a8402f202caffb66703ae1620 Mon Sep 17 00:00:00 2001 From: Spencer Fields <58378262+sgf36@users.noreply.github.com> Date: Tue, 29 Sep 2026 12:07:19 +0100 Subject: [PATCH 4/4] Add font coverage and tofu detection to screenshot pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two guards against publishing screenshots with encoding corruption: 1. Pre-render: _check_font_coverage() queries QFontDatabase for the locale's writing system and exits immediately if no fonts are available, so the CI log names the cause instead of producing bad images. 2. Post-render: audit_for_tofu() checks each PNG's bits-per-pixel ratio and flags abnormally low-complexity images that may contain tofu. Both run inside make_screenshots.py itself — no separate CI step needed. Co-Authored-By: Claude Opus 4.6 --- packaging/make_screenshots.py | 142 ++++++++++++++++++++++++++++++++- tests/test_screenshot_guard.py | 42 ++++++++++ 2 files changed, 183 insertions(+), 1 deletion(-) diff --git a/packaging/make_screenshots.py b/packaging/make_screenshots.py index d13a20d..b6fa584 100644 --- a/packaging/make_screenshots.py +++ b/packaging/make_screenshots.py @@ -56,6 +56,130 @@ sys.path.insert(0, str(REPO_ROOT)) +# --------------------------------------------------------------------------- +# Font coverage check — catch missing glyphs before rendering, not after. +# +# When the CI runner lacks fonts for a locale's primary script (Bengali, +# Telugu, …), Qt renders every native-script character as a tofu rectangle +# (□). The resulting screenshots are useless, and the run looks green. +# +# _LOCALE_WRITING_SYSTEMS maps each supported locale to its Qt WritingSystem. +# _check_font_coverage() queries QFontDatabase.families(writing_system) after +# the QApplication exists, and fails the job immediately if no fonts are +# available — so the error names the cause rather than producing bad images. +# --------------------------------------------------------------------------- + +_LOCALE_WRITING_SYSTEMS: dict[str, str] = { + "am": None, # Ethiopic — no matching Qt enum; skipped + "ar": "Arabic", + "bn": "Bengali", + "cs": "Latin", + "de": "Latin", + "el": "Greek", + "en": "Latin", + "es": "Latin", + "fa": "Arabic", + "fr": "Latin", + "gu": "Gujarati", + "ha": "Latin", + "he": "Hebrew", + "hi": "Devanagari", + "hr": "Latin", + "hu": "Latin", + "id": "Latin", + "ig": "Latin", + "it": "Latin", + "ja": "Japanese", + "jv": "Latin", + "kn": "Kannada", + "ko": "Korean", + "ml": "Malayalam", + "mr": "Devanagari", + "ms": "Latin", + "my": "Myanmar", + "ne": "Devanagari", + "nl": "Latin", + "or": "Oriya", + "pa": "Gurmukhi", + "pl": "Latin", + "pt": "Latin", + "ro": "Latin", + "ru": "Cyrillic", + "si": "Sinhala", + "so": "Latin", + "sv": "Latin", + "sw": "Latin", + "ta": "Tamil", + "te": "Telugu", + "th": "Thai", + "tr": "Latin", + "uk": "Cyrillic", + "ur": "Arabic", + "uz": "Latin", + "vi": "Vietnamese", + "yo": "Latin", + "zh": "SimplifiedChinese", + "zu": "Latin", +} + + +def _check_font_coverage(locale: str) -> list[str]: + """Verify the system has fonts for the locale's primary script. + + Returns a list of problem descriptions (empty = all clear). Must be + called after QApplication exists. + """ + from PySide6.QtGui import QFontDatabase + + ws_name = _LOCALE_WRITING_SYSTEMS.get(locale) + if ws_name is None: + return [] + + ws = getattr(QFontDatabase.WritingSystem, ws_name, None) + if ws is None: + return [] + + families = QFontDatabase.families(ws) + if not families: + return [ + f"No fonts found for {ws_name} script (locale '{locale}'). " + f"Screenshots will contain tofu characters (□). " + f"Install a font covering this script on the runner." + ] + return [] + + +def audit_for_tofu(root: Path) -> list[str]: + """Post-render check: flag screenshots with suspiciously low complexity. + + A belt-and-braces pass after the font check. Opens each PNG and checks + that the content area has enough visual variation to contain real text. + Tofu characters compress into very uniform images, so an abnormally small + file relative to its pixel count is a warning sign. + """ + from PIL import Image + + problems = [] + for png in sorted(root.rglob("*.png")): + img = Image.open(png) + pixel_count = img.width * img.height + file_bytes = png.stat().st_size + if pixel_count == 0: + problems.append(f"{png.name}: empty image") + continue + bits_per_pixel = (file_bytes * 8) / pixel_count + # Real screenshots with anti-aliased text and UI chrome compress to + # roughly 1–6 bits/pixel in PNG. Pure tofu with uniform backgrounds + # compresses below 0.1. A threshold of 0.15 catches obvious cases + # without false-positiving on sparse-but-real pages. + if bits_per_pixel < 0.15: + problems.append( + f"{png.name}: unusually low complexity " + f"({bits_per_pixel:.2f} bits/px) — may contain tofu text" + ) + return problems + + # Store-required canvas sizes, in logical pixels, with the scale factor each is # rendered at. Apple and Microsoft both police these dimensions, so they are # produced exactly rather than resized afterwards. @@ -1019,6 +1143,14 @@ def main() -> int: app = QApplication.instance() or QApplication([]) print(f"Qt platform plugin: {app.platformName()}") + + font_problems = _check_font_coverage(args.locale) + if font_problems: + for p in font_problems: + print(f"FONT ERROR: {p}") + sys.stdout.flush() + os._exit(3) + if args.unseeded: from app.core.db import init_db @@ -1126,6 +1258,13 @@ def main() -> int: shutil.rmtree(scratch, ignore_errors=True) print(f"{written} screenshot(s) written to {out_root}") + + tofu_problems = audit_for_tofu(out_root) + if tofu_problems: + print(f"\n{len(tofu_problems)} screenshot(s) may have encoding issues:") + for p in tofu_problems: + print(f" WARNING: {p}") + sys.stdout.flush() # Leave immediately rather than unwinding Qt. @@ -1137,7 +1276,8 @@ def main() -> int: # disk, but with a non-zero exit code that would fail the CI job for no # real reason. Every file is written and flushed by this point, so there is # nothing left to clean up. - os._exit(0 if written else 1) + exit_code = 0 if written and not tofu_problems else 1 + os._exit(exit_code) def audit_for_secrets(root: Path) -> list[str]: diff --git a/tests/test_screenshot_guard.py b/tests/test_screenshot_guard.py index 2c5d39d..c6e7a4e 100644 --- a/tests/test_screenshot_guard.py +++ b/tests/test_screenshot_guard.py @@ -77,3 +77,45 @@ def test_audit_flags_a_forbidden_capture(shots, tmp_path): def test_audit_allows_a_settings_capture(shots, tmp_path): (tmp_path / "en_9_settings.png").write_bytes(b"") assert shots.audit_for_secrets(tmp_path) == [] + + +# ── Font coverage and tofu detection ────────────────────────────────────── + + +def test_locale_writing_system_mapping_covers_all_locales(shots): + """Every locale JSON must have an entry in the writing system mapping.""" + locales_dir = REPO_ROOT / "app" / "resources" / "locales" + for f in sorted(locales_dir.glob("*.json")): + locale = f.stem + assert locale in shots._LOCALE_WRITING_SYSTEMS, ( + f"Locale '{locale}' has no entry in _LOCALE_WRITING_SYSTEMS" + ) + + +def test_audit_for_tofu_flags_tiny_images(shots, tmp_path): + """A PNG with near-zero complexity should be flagged.""" + from PIL import Image + + img = Image.new("RGB", (400, 300), color=(255, 255, 255)) + path = tmp_path / "blank.png" + img.save(str(path), "PNG") + problems = shots.audit_for_tofu(tmp_path) + assert len(problems) == 1 + assert "blank.png" in problems[0] + + +def test_audit_for_tofu_passes_complex_images(shots, tmp_path): + """A PNG with real visual content should pass.""" + from PIL import Image, ImageDraw + + img = Image.new("RGB", (400, 300), color=(245, 245, 245)) + draw = ImageDraw.Draw(img) + for y in range(0, 300, 20): + for x in range(0, 400, 15): + draw.rectangle([x, y, x + 10, y + 12], fill=(50, 50, 50)) + draw.text((20, 20), "Create Shipment", fill=(0, 0, 0)) + draw.text((20, 50), "Royal Mail Click & Drop", fill=(0, 0, 0)) + path = tmp_path / "good.png" + img.save(str(path), "PNG") + problems = shots.audit_for_tofu(tmp_path) + assert problems == []