+ {[items.length > 0 ? t("items_count", { count }) : undefined, total ? t("total", { total }) : undefined]
+ .filter(Boolean).join(" · ")}
+
+ )}
+ {shipment.parcels.map((parcel, i) => ;
+ /** Whether remote content may load for this message: product images show only then. */
+ allowRemoteImages: boolean;
+ /** Rendered in each booking card's action row ("Add to calendar"); nothing when undefined. */
+ calendarActions?: (booking: Booking) => ReactNode;
+}
+
+/** The booking, parcel and order cards shown above an open message. */
+export function StructuredMailCards({ cards, email, allowRemoteImages, calendarActions }: StructuredMailCardsProps) {
+ if (cards.length === 0) return null;
+ return (
+
+ {cards.map((card, i) => {
+ const props = { emailId: email.id, calendarActions };
+ switch (card.kind) {
+ case "flight":
+ case "train":
+ case "bus":
+ return ;
+ case "lodging":
+ return ;
+ case "rentalcar":
+ return ;
+ case "event":
+ return ;
+ case "restaurant":
+ return ;
+ case "shipment":
+ return ;
+ default:
+ return null;
+ }
+ })}
+
+ );
+}
diff --git a/components/email/thread-conversation-view.tsx b/components/email/thread-conversation-view.tsx
index f078f8d06..99ff0cc68 100644
--- a/components/email/thread-conversation-view.tsx
+++ b/components/email/thread-conversation-view.tsx
@@ -11,6 +11,8 @@ import { emailDisplayDate } from "@/lib/email-date";
import { getRenderableHtmlBody } from "@/lib/email-body-selection";
import { findVerificationCode, verificationCodeBodyText } from "@/lib/verification-code";
import { VerificationCodeChip } from "./verification-code-chip";
+import { StructuredMailCards } from "./structured-mail/structured-mail-cards";
+import { useStructuredMail } from "./structured-mail/use-structured-mail";
import { attachmentIcon } from "./attachment-chips";
import { ExternalSenderChip } from "./external-sender-chip";
import { collectReferencedCids, isEmbeddedInBody, normalizeCid, rewriteCidReferences } from "@/lib/attachment-visibility";
@@ -565,6 +567,8 @@ export function ConversationEmailBody({
const fallbackSource = useEmailStore(useShallow(() => resolveEmailBlobContext(email, client)));
const source = blobSource ?? fallbackSource;
const { client: blobClient, accountId } = source;
+ // Booking, parcel and order cards; only an expanded message mounts this body.
+ const structuredCards = useStructuredMail(email, source);
// Local CID URLs belong to a particular client/owner/message/part list.
// Hide the previous set during render, before the new fetch's effect runs.
const cidRequest = useMemo(() => ({ blobClient, accountId, emailId: email.id, attachments: email.attachments }),
@@ -929,6 +933,15 @@ export function ConversationEmailBody({
)}
+ {structuredCards.length > 0 && (
+ // Aligned with the body: its own padding on the phone card, the
+ // caller's (className) in Mountain View.
+
+ {/* No product images when the mail is shown as plain text. */}
+
+
+ )}
+
{/* Email Body */}
{emailContent.isHtml ? (
diff --git a/lib/structured-mail/__tests__/format.test.ts b/lib/structured-mail/__tests__/format.test.ts
new file mode 100644
index 000000000..cbaca2eb1
--- /dev/null
+++ b/lib/structured-mail/__tests__/format.test.ts
@@ -0,0 +1,188 @@
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
+import {
+ formatAddress,
+ formatMoment,
+ formatMomentDate,
+ formatMomentTime,
+ formatMoney,
+ isOtherZone,
+ isWebLink,
+ legPlaceLabel,
+ legService,
+ momentOffsetMinutes,
+ nightsBetween,
+ routeTitle,
+ shipmentItems,
+ summarizeItems,
+} from '../format';
+import type { Moment, Shipment, TransportBooking, TransportLeg } from '../types';
+
+const NOW = new Date('2026-10-30T12:00:00Z');
+const en = { locale: 'en-US', hour12: false, now: NOW } as const;
+
+// SFO 20:15 −08:00 = 04:15Z the next day; JFK 06:30 −05:00.
+const SFO_DEP: Moment = { date: '2026-12-03', time: '20:15:00', offsetMinutes: -480, utc: '2026-12-04T04:15:00Z', zone: 'America/Los_Angeles' };
+const BERLIN: Moment = { date: '2026-12-01', time: '10:15:00', offsetMinutes: 60, utc: '2026-12-01T09:15:00Z', zone: 'Europe/Berlin' };
+// A floating time the airport table resolved: no offset in the mail, utc from the zone.
+const NRT_RESOLVED: Moment = { date: '2026-12-02', time: '17:40:00', utc: '2026-12-02T08:40:00Z', zone: 'Asia/Tokyo' };
+
+const originalTz = process.env.TZ;
+afterEach(() => {
+ process.env.TZ = originalTz;
+});
+
+describe('wall-clock formatting', () => {
+ for (const tz of ['UTC', 'America/Los_Angeles', 'Europe/Berlin', 'Asia/Tokyo', 'Pacific/Kiritimati']) {
+ it(`keeps 20:15 −08:00 at 20:15 on 3 Dec with TZ=${tz}`, () => {
+ process.env.TZ = tz;
+ expect(formatMomentTime(SFO_DEP, en)).toBe('20:15');
+ expect(formatMomentDate(SFO_DEP, en)).toBe('Thu, Dec 3');
+ expect(formatMoment(SFO_DEP, en)).toBe('Thu, Dec 3, 20:15');
+ });
+ }
+
+ it('shows the clock the mail gave whatever the offset', () => {
+ const tokyo: Moment = { date: '2026-12-02', time: '07:05:00', offsetMinutes: 540, utc: '2026-12-01T22:05:00Z' };
+ const kolkata: Moment = { date: '2026-12-02', time: '23:50:00', offsetMinutes: 330, utc: '2026-12-02T18:20:00Z' };
+ expect(formatMoment(tokyo, en)).toBe('Wed, Dec 2, 07:05');
+ expect(formatMoment(kolkata, en)).toBe('Wed, Dec 2, 23:50');
+ });
+
+ it('formats a date-only moment without a time', () => {
+ const d: Moment = { date: '2027-06-01' };
+ expect(formatMomentTime(d, en)).toBeUndefined();
+ // Another year than "now": the year is shown.
+ expect(formatMoment(d, en)).toBe('Tue, Jun 1, 2027');
+ expect(formatMomentDate({ date: '2026-11-03' }, en)).toBe('Tue, Nov 3');
+ });
+
+ it('follows the UI locale and the 12-hour setting', () => {
+ expect(formatMoment(BERLIN, { locale: 'de', hour12: false, now: NOW })).toBe('Di., 1. Dez., 10:15');
+ expect(formatMomentTime(SFO_DEP, { locale: 'en-US', hour12: true, now: NOW })).toBe('8:15 PM');
+ });
+
+ it('accepts HH:mm and falls back to the raw value for a malformed moment', () => {
+ expect(formatMomentTime({ date: '2026-12-01', time: '09:05' }, en)).toBe('09:05');
+ expect(formatMomentDate({ date: 'soon' }, en)).toBe('soon');
+ });
+});
+
+describe('local-time hint', () => {
+ it('knows the offset of a moment from the mail or from its resolved zone', () => {
+ expect(momentOffsetMinutes(SFO_DEP)).toBe(-480);
+ expect(momentOffsetMinutes(NRT_RESOLVED)).toBe(540);
+ expect(momentOffsetMinutes({ date: '2026-12-01', time: '10:00:00' })).toBeUndefined();
+ expect(momentOffsetMinutes({ date: '2026-12-01' })).toBeUndefined();
+ });
+
+ it('marks a time whose place keeps another clock than the reader', () => {
+ expect(isOtherZone(SFO_DEP, 'Europe/Berlin')).toBe(true);
+ expect(isOtherZone(SFO_DEP, 'America/Los_Angeles')).toBe(false);
+ expect(isOtherZone(NRT_RESOLVED, 'Asia/Tokyo')).toBe(false);
+ expect(isOtherZone(NRT_RESOLVED, 'Europe/Berlin')).toBe(true);
+ });
+
+ it('compares at the instant, so DST on the reader side counts', () => {
+ // 10:15 +01:00 in December: Berlin is +01:00 then, London +00:00.
+ expect(isOtherZone(BERLIN, 'Europe/Berlin')).toBe(false);
+ expect(isOtherZone(BERLIN, 'Europe/London')).toBe(true);
+ // A +02:00 time in July matches Berlin's summer time.
+ expect(isOtherZone({ date: '2026-07-18', time: '14:00:00', offsetMinutes: 120, utc: '2026-07-18T12:00:00Z' }, 'Europe/Berlin')).toBe(false);
+ expect(isOtherZone(BERLIN, 'x', () => 60)).toBe(false);
+ expect(isOtherZone(BERLIN, 'x', () => 0)).toBe(true);
+ });
+
+ it('never marks a floating or date-only moment', () => {
+ expect(isOtherZone({ date: '2026-12-01', time: '10:00:00', zone: null }, 'Asia/Tokyo')).toBe(false);
+ expect(isOtherZone({ date: '2026-12-01' }, 'Asia/Tokyo')).toBe(false);
+ });
+});
+
+describe('card text helpers', () => {
+ const leg = (from: string, to: string, extra: Partial = {}): TransportLeg => ({
+ carrier: 'Lufthansa', carrierCode: 'LH', number: '400',
+ departure: { place: { code: from, name: `${from} Airport` }, at: BERLIN },
+ arrival: { place: { code: to }, at: SFO_DEP },
+ seats: [], ...extra,
+ });
+ const flight = (legs: TransportLeg[]): TransportBooking => ({ key: 'k', kind: 'flight', passengers: [], links: {}, source: 'json-ld', legs });
+
+ it('titles a flight with airport codes, chaining connecting legs', () => {
+ expect(routeTitle(flight([leg('FRA', 'JFK')]))).toBe('FRA → JFK');
+ expect(routeTitle(flight([leg('FRA', 'JFK'), leg('JFK', 'FRA')]))).toBe('FRA → JFK → FRA');
+ expect(routeTitle(flight([leg('FRA', 'JFK'), leg('BOS', 'FRA')]))).toBe('FRA → JFK, BOS → FRA');
+ });
+
+ it('titles a train with towns when every stop has one, else station names', () => {
+ const station = (name: string, locality?: string) => ({ name, ...(locality ? { address: { locality } } : {}) });
+ const train = (a: ReturnType, b: ReturnType): TransportBooking => ({
+ key: 'k', kind: 'train', passengers: [], links: {}, source: 'json-ld',
+ legs: [{ departure: { place: a, at: BERLIN }, arrival: { place: b, at: BERLIN }, seats: [] }],
+ });
+ expect(routeTitle(train(station('Hamburg Hbf', 'Hamburg'), station('München Hbf', 'München')))).toBe('Hamburg → München');
+ expect(routeTitle(train(station('Hamburg Hbf', 'Hamburg'), station('München Hbf')))).toBe('Hamburg Hbf → München Hbf');
+ expect(routeTitle(train(station('Berlin Hbf', 'Berlin'), station('Berlin Südkreuz', 'Berlin')))).toBe('Berlin Hbf → Berlin Südkreuz');
+ });
+
+ it('labels airports and services', () => {
+ expect(legPlaceLabel({ code: 'FRA', name: 'Frankfurt Airport' }, 'flight')).toBe('Frankfurt Airport (FRA)');
+ expect(legPlaceLabel({ code: 'FRA' }, 'flight')).toBe('FRA');
+ expect(legPlaceLabel({ code: 'JFK', name: 'New York JFK' }, 'flight')).toBe('New York JFK');
+ expect(legPlaceLabel({ name: 'Hamburg Hbf', code: 'X' }, 'train')).toBe('Hamburg Hbf');
+ expect(legService(leg('FRA', 'JFK'))).toBe('Lufthansa LH 400');
+ expect(legService({ ...leg('FRA', 'JFK'), carrierCode: undefined, carrier: 'Flix', number: 'FLX30' })).toBe('Flix FLX30');
+ });
+
+ it('counts nights by date', () => {
+ expect(nightsBetween({ date: '2026-12-04', time: '15:00:00' }, { date: '2026-12-06', time: '11:00:00' })).toBe(2);
+ expect(nightsBetween({ date: '2027-03-27' }, { date: '2027-03-29' })).toBe(2);
+ expect(nightsBetween({ date: '2027-03-29' }, { date: '2027-03-29' })).toBeUndefined();
+ });
+
+ it('formats money in the UI locale with the card currency', () => {
+ expect(formatMoney({ amount: '129.90', currency: 'EUR' }, 'en-US')).toBe('€129.90');
+ expect(formatMoney({ amount: '1299.00', currency: 'EUR' }, 'de').replace(/\s/g, ' ')).toBe('1.299,00 €');
+ expect(formatMoney({ amount: '25.99', currency: 'USD' }, 'en-US')).toBe('$25.99');
+ expect(formatMoney({ amount: '5.00', currency: 'XX1' }, 'en-US')).toBe('5.00 XX1');
+ });
+
+ it('writes an address on one line without repeating a combined street', () => {
+ expect(formatAddress({ street: 'Marktplatz 1', postalCode: '10178', locality: 'Berlin', country: 'DE' }, 'en')).toBe('Marktplatz 1, 10178 Berlin, Germany');
+ expect(formatAddress({ street: 'Kurfürstendamm 18, 10719 Berlin' }, 'en')).toBe('Kurfürstendamm 18, 10719 Berlin');
+ expect(formatAddress({}, 'en')).toBeUndefined();
+ });
+
+ it('lists the first three items and counts pieces', () => {
+ const items = [{ name: 'A', quantity: 2 }, { name: 'B' }, { name: 'C' }, { name: 'D' }, { name: 'E', quantity: 3 }];
+ const s = summarizeItems(items);
+ expect(s.shown.map((i) => i.name)).toEqual(['A', 'B', 'C']);
+ expect(s.more).toBe(2);
+ expect(s.count).toBe(8);
+ });
+
+ it('takes item images from the parcel when the order has none', () => {
+ const shipment: Shipment = {
+ kind: 'shipment', key: 'k', items: [{ name: 'Shoes', quantity: 1 }], source: 'json-ld',
+ parcels: [{ items: [{ name: 'Shoes', image: { url: 'https://img.example.com/1.jpg', host: 'img.example.com' } }] }],
+ };
+ expect(shipmentItems(shipment)[0].image?.host).toBe('img.example.com');
+ expect(shipmentItems({ ...shipment, items: [] }).map((i) => i.name)).toEqual(['Shoes']);
+ });
+
+ it('accepts only http(s) links', () => {
+ expect(isWebLink({ url: 'https://dhl.de/x' })).toBe(true);
+ expect(isWebLink({ url: 'http://dhl.de/x' })).toBe(true);
+ expect(isWebLink({ url: 'javascript:alert(1)' })).toBe(false);
+ expect(isWebLink({ url: 'data:text/html,x' })).toBe(false);
+ expect(isWebLink({ url: 'not a url' })).toBe(false);
+ });
+});
+
+describe('formatting does not depend on the process zone', () => {
+ beforeEach(() => {
+ process.env.TZ = 'Pacific/Honolulu';
+ });
+ it('keeps a Berlin morning a Berlin morning in Honolulu', () => {
+ expect(formatMoment(BERLIN, en)).toBe('Tue, Dec 1, 10:15');
+ });
+});
diff --git a/lib/structured-mail/format.ts b/lib/structured-mail/format.ts
new file mode 100644
index 000000000..bd2b6203c
--- /dev/null
+++ b/lib/structured-mail/format.ts
@@ -0,0 +1,260 @@
+/**
+ * Text for the reader cards. Plain TypeScript, no React.
+ *
+ * A card shows a time the way the mail gave it: the wall clock at the place
+ * (departure airport, hotel, venue), never converted to the reader's zone.
+ * The local date and time are formatted as if they were UTC, with
+ * `timeZone: 'UTC'`, so neither the browser's zone nor DST can move them.
+ */
+import { zoneOffsetAt } from './time-zones';
+import type { Address, Item, Moment, Place, Shipment, TransportBooking, TransportLeg } from './types';
+
+const MINUTE = 60_000;
+const DAY = 24 * 60 * MINUTE;
+
+const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
+const TIME_RE = /^\d{2}:\d{2}(?::\d{2})?$/;
+
+export interface FormatOptions {
+ /** UI locale ("en", "de", ...). */
+ locale: string;
+ /** true for a 12-hour clock, false for 24 hours, undefined for the locale's own. */
+ hour12?: boolean;
+ /** "Now", to decide whether the year is shown. Defaults to the current date. */
+ now?: Date;
+}
+
+/** The moment's local wall clock as a Date whose UTC fields hold it; null when malformed. */
+export function wallClockDate(m: Moment): Date | null {
+ if (!DATE_RE.test(m.date)) return null;
+ if (m.time !== undefined && !TIME_RE.test(m.time)) return null;
+ const time = m.time ? (m.time.length === 5 ? `${m.time}:00` : m.time) : '00:00:00';
+ const d = new Date(`${m.date}T${time}Z`);
+ return Number.isNaN(d.getTime()) ? null : d;
+}
+
+function formatter(options: Intl.DateTimeFormatOptions, opts: FormatOptions): Intl.DateTimeFormat {
+ try {
+ return new Intl.DateTimeFormat(opts.locale, { ...options, timeZone: 'UTC' });
+ } catch {
+ return new Intl.DateTimeFormat('en', { ...options, timeZone: 'UTC' });
+ }
+}
+
+function clockOptions(opts: FormatOptions): Intl.DateTimeFormatOptions {
+ if (opts.hour12 === true) return { hour: 'numeric', minute: '2-digit', hour12: true };
+ if (opts.hour12 === false) return { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' };
+ return { hour: 'numeric', minute: '2-digit' };
+}
+
+function dateOptions(m: Moment, opts: FormatOptions): Intl.DateTimeFormatOptions {
+ const year = Number(m.date.slice(0, 4));
+ const currentYear = (opts.now ?? new Date()).getUTCFullYear();
+ return { weekday: 'short', day: 'numeric', month: 'short', ...(year !== currentYear ? { year: 'numeric' } : {}) };
+}
+
+/** "Tue, Dec 1" (the year only when it isn't this year). */
+export function formatMomentDate(m: Moment, opts: FormatOptions): string {
+ const d = wallClockDate(m);
+ return d ? formatter(dateOptions(m, opts), opts).format(d) : m.date;
+}
+
+/** "10:15", or undefined for a date-only moment. */
+export function formatMomentTime(m: Moment, opts: FormatOptions): string | undefined {
+ if (!m.time) return undefined;
+ const d = wallClockDate(m);
+ return d ? formatter(clockOptions(opts), opts).format(d) : m.time.slice(0, 5);
+}
+
+/** "Tue, Dec 1, 10:15" in the locale's own order; the date alone for a date-only moment. */
+export function formatMoment(m: Moment, opts: FormatOptions): string {
+ if (!m.time) return formatMomentDate(m, opts);
+ const d = wallClockDate(m);
+ if (!d) return `${m.date} ${m.time.slice(0, 5)}`;
+ return formatter({ ...dateOptions(m, opts), ...clockOptions(opts) }, opts).format(d);
+}
+
+/** Whether two moments fall on the same local date. */
+export function sameLocalDate(a: Moment, b: Moment): boolean {
+ return a.date === b.date;
+}
+
+/**
+ * The moment's UTC offset in minutes east of UTC: the one the mail gave, or
+ * the one its resolved zone implies. Undefined for a floating time (shown as
+ * written, no zone known) or a date-only moment.
+ */
+export function momentOffsetMinutes(m: Moment): number | undefined {
+ if (!m.time) return undefined;
+ if (m.offsetMinutes !== undefined) return m.offsetMinutes;
+ if (!m.utc) return undefined;
+ const wall = wallClockDate(m);
+ const instant = Date.parse(m.utc);
+ if (!wall || Number.isNaN(instant)) return undefined;
+ return Math.round((wall.getTime() - instant) / MINUTE);
+}
+
+function instantOf(m: Moment, offset: number): number | undefined {
+ if (m.utc) {
+ const t = Date.parse(m.utc);
+ if (!Number.isNaN(t)) return t;
+ }
+ const wall = wallClockDate(m);
+ return wall ? wall.getTime() - offset * MINUTE : undefined;
+}
+
+/**
+ * Whether a timed moment's place keeps a different clock than the reader
+ * at that instant, so the card marks the time as local to the place.
+ * `readerOffsetAt` gives the reader's offset (minutes east of UTC) at an
+ * instant; by default the offset of `readerZone`.
+ */
+export function isOtherZone(m: Moment, readerZone: string, readerOffsetAt?: (utcMs: number) => number): boolean {
+ const offset = momentOffsetMinutes(m);
+ if (offset === undefined) return false;
+ const instant = instantOf(m, offset);
+ if (instant === undefined) return false;
+ try {
+ const reader = readerOffsetAt ? readerOffsetAt(instant) : zoneOffsetAt(readerZone, instant);
+ return reader !== offset;
+ } catch {
+ return false;
+ }
+}
+
+/** Nights between check-in and check-out dates; undefined when it doesn't add up. */
+export function nightsBetween(checkin: Moment, checkout: Moment): number | undefined {
+ const a = wallClockDate({ date: checkin.date });
+ const b = wallClockDate({ date: checkout.date });
+ if (!a || !b) return undefined;
+ const nights = Math.round((b.getTime() - a.getTime()) / DAY);
+ return nights > 0 ? nights : undefined;
+}
+
+/** "€129.90" in the UI locale; amount and code as given when Intl can't format them. */
+export function formatMoney(total: { amount: string; currency: string }, locale: string): string {
+ const n = Number(total.amount);
+ if (!Number.isFinite(n)) return `${total.amount} ${total.currency}`;
+ try {
+ return new Intl.NumberFormat(locale, { style: 'currency', currency: total.currency }).format(n);
+ } catch {
+ return `${total.amount} ${total.currency}`;
+ }
+}
+
+function regionName(code: string | undefined, locale: string): string | undefined {
+ if (!code) return undefined;
+ try {
+ return new Intl.DisplayNames([locale], { type: 'region' }).of(code) ?? code;
+ } catch {
+ return code;
+ }
+}
+
+/** One line: "Marktplatz 1, 10178 Berlin, Germany". */
+export function formatAddress(address: Address | undefined, locale: string): string | undefined {
+ if (!address) return undefined;
+ const town = [address.postalCode, address.locality].filter(Boolean).join(' ');
+ const country = address.countryName ?? regionName(address.country, locale);
+ const parts = [address.street, town, address.region, country].filter((p): p is string => !!p && p.trim() !== '');
+ // A street given as one string may already hold the town.
+ const unique = parts.filter((p, i) => !parts.slice(0, i).some((q) => q.includes(p)));
+ return unique.length ? unique.join(', ') : undefined;
+}
+
+/** A place on one line: "Stadtpark, Hamburg"; the name alone when it already names the town. */
+export function formatPlace(place: Place | undefined): string | undefined {
+ if (!place) return undefined;
+ const name = place.name?.trim();
+ const town = place.address?.locality?.trim();
+ if (name && town && !name.toLowerCase().includes(town.toLowerCase())) return `${name}, ${town}`;
+ return name || town || place.code;
+}
+
+/** An airport or station in a leg row: "Frankfurt Airport (FRA)", "Hamburg Hbf". */
+export function legPlaceLabel(place: Place, kind: TransportBooking['kind']): string {
+ const name = place.name?.trim() || place.address?.locality?.trim();
+ if (kind === 'flight' && place.code) {
+ if (!name) return place.code;
+ // "Frankfurt" holds the letters FRA; only a code standing on its own counts.
+ const code = place.code.toUpperCase().replace(/[^A-Z0-9]/g, '');
+ const hasCode = new RegExp(`(^|[^A-Z0-9])${code}([^A-Z0-9]|$)`).test(name.toUpperCase());
+ return hasCode ? name : `${name} (${place.code})`;
+ }
+ return name || place.code || '';
+}
+
+/** Carrier and number: "Lufthansa LH 400", "Rail Co ICE 577". */
+export function legService(leg: TransportLeg): string | undefined {
+ const number = leg.carrierCode && leg.number && !leg.number.toUpperCase().startsWith(leg.carrierCode.toUpperCase())
+ ? `${leg.carrierCode} ${leg.number}`
+ : leg.number;
+ const parts = [leg.carrier, number].filter((p): p is string => !!p);
+ return parts.length ? parts.join(' ') : undefined;
+}
+
+/**
+ * The stops of a route, for its title: airport codes for flights, city or
+ * station names otherwise. Connecting legs form one run (FRA, JFK, FRA);
+ * a leg that doesn't connect starts the next run.
+ */
+export function routeRuns(booking: TransportBooking): string[][] {
+ const legs = booking.legs;
+ const towns = legs.flatMap((leg) => [leg.departure.place, leg.arrival?.place]).filter((p): p is Place => !!p)
+ .map((p) => p.address?.locality?.trim());
+ const useTowns = booking.kind !== 'flight' && towns.every(Boolean)
+ && legs.every((leg) => !leg.arrival || leg.departure.place.address?.locality !== leg.arrival.place.address?.locality);
+ const label = (place: Place): string => {
+ if (booking.kind === 'flight' && place.code) return place.code;
+ if (useTowns && place.address?.locality) return place.address.locality.trim();
+ return place.name?.trim() || place.address?.locality?.trim() || place.code || '?';
+ };
+ const runs: string[][] = [];
+ for (const leg of legs) {
+ const from = label(leg.departure.place);
+ const to = leg.arrival ? label(leg.arrival.place) : undefined;
+ const run = runs[runs.length - 1];
+ if (run && run[run.length - 1] === from) {
+ if (to) run.push(to);
+ } else {
+ runs.push(to ? [from, to] : [from]);
+ }
+ }
+ return runs;
+}
+
+/** The route as plain text, "FRA → JFK → FRA"; runs separated by a comma. */
+export function routeTitle(booking: TransportBooking): string {
+ return routeRuns(booking).map((run) => run.join(' → ')).join(', ');
+}
+
+/** The items a shipment card lists: the order's, else the parcels', with images from either. */
+export function shipmentItems(shipment: Shipment): Item[] {
+ const parcelItems = shipment.parcels.flatMap((p) => p.items);
+ if (shipment.items.length === 0) {
+ const seen = new Set();
+ return parcelItems.filter((item) => (seen.has(item.name) ? false : (seen.add(item.name), true)));
+ }
+ return shipment.items.map((item) => {
+ if (item.image) return item;
+ const image = parcelItems.find((p) => p.name === item.name && p.image)?.image;
+ return image ? { ...item, image } : item;
+ });
+}
+
+/** The first `max` item names, how many more there are, and the number of pieces. */
+export function summarizeItems(items: Item[], max = 3): { shown: Item[]; more: number; count: number } {
+ const count = items.reduce((sum, item) => sum + (item.quantity && item.quantity > 0 ? item.quantity : 1), 0);
+ return { shown: items.slice(0, max), more: Math.max(0, items.length - max), count };
+}
+
+/** Whether a link may be shown and opened: http(s) only, checked again here. */
+export function isWebLink(link: { url: string } | undefined): boolean {
+ if (!link) return false;
+ try {
+ const { protocol } = new URL(link.url);
+ return protocol === 'http:' || protocol === 'https:';
+ } catch {
+ return false;
+ }
+}
diff --git a/locales/ar/common.json b/locales/ar/common.json
index 5011d5623..5e23c851f 100644
--- a/locales/ar/common.json
+++ b/locales/ar/common.json
@@ -775,6 +775,69 @@
"copied": "تم نسخ الرمز",
"copy_failed": "تعذّر نسخ الرمز"
},
+ "structured_mail": {
+ "kind_flight": "رحلة جوية",
+ "kind_train": "قطار",
+ "kind_bus": "حافلة",
+ "kind_lodging": "فندق",
+ "kind_rentalcar": "سيارة مستأجرة",
+ "kind_event": "فعالية",
+ "kind_restaurant": "مطعم",
+ "kind_order": "طلب",
+ "kind_parcel": "طرد",
+ "region_flight": "حجز رحلة جوية",
+ "region_train": "حجز قطار",
+ "region_bus": "حجز حافلة",
+ "region_lodging": "حجز فندق",
+ "region_rentalcar": "حجز سيارة مستأجرة",
+ "region_event": "حجز فعالية",
+ "region_restaurant": "حجز مطعم",
+ "region_shipment": "الطلب والتوصيل",
+ "status_cancelled": "ملغى",
+ "status_pending": "قيد الانتظار",
+ "status_hold": "محجوز مؤقتًا",
+ "order_status_payment_due": "بانتظار الدفع",
+ "order_status_processing": "قيد التجهيز",
+ "order_status_problem": "مشكلة",
+ "order_status_in_transit": "تم الشحن",
+ "order_status_pickup_available": "جاهز للاستلام",
+ "order_status_returned": "مُرتجع",
+ "order_status_delivered": "تم التوصيل",
+ "order_status_cancelled": "ملغى",
+ "reference": "رقم الحجز",
+ "order_number": "رقم الطلب",
+ "tracking_number": "رقم التتبع",
+ "copy_reference": "نسخ رقم الحجز {value}",
+ "copy_order_number": "نسخ رقم الطلب {value}",
+ "copy_tracking_number": "نسخ رقم التتبع {value}",
+ "copied_reference": "تم نسخ رقم الحجز",
+ "copied_order_number": "تم نسخ رقم الطلب",
+ "copied_tracking_number": "تم نسخ رقم التتبع",
+ "copy_failed": "تعذّر النسخ إلى الحافظة",
+ "passengers": "المسافرون",
+ "seats": "المقاعد",
+ "tickets": "التذاكر",
+ "link_check_in": "تسجيل الوصول",
+ "link_manage": "إدارة الحجز",
+ "link_ticket": "التذكرة",
+ "link_track": "تتبّع",
+ "link_view_order": "عرض الطلب",
+ "check_in_label": "تسجيل الوصول",
+ "check_out_label": "تسجيل المغادرة",
+ "from_time": "من الساعة {time}",
+ "until_time": "حتى الساعة {time}",
+ "nights": "{count, plural, zero {# ليلة} one {ليلة واحدة} two {ليلتان} few {# ليالٍ} many {# ليلة} other {# ليلة}}",
+ "pickup": "الاستلام",
+ "dropoff": "الإرجاع",
+ "party_size": "{count, plural, zero {طاولة لـ # شخص} one {طاولة لشخص واحد} two {طاولة لشخصين} few {طاولة لـ # أشخاص} many {طاولة لـ # شخصًا} other {طاولة لـ # شخص}}",
+ "items_more": "و{count} أخرى",
+ "items_count": "{count, plural, zero {# منتج} one {منتج واحد} two {منتجان} few {# منتجات} many {# منتجًا} other {# منتج}}",
+ "total": "الإجمالي {total}",
+ "expected_by": "يصل بحلول {date}",
+ "local_time": "بالتوقيت المحلي",
+ "local_time_title": "بالتوقيت المحلي للمكان، وليس بمنطقتك الزمنية",
+ "route": "{from} إلى {to}"
+ },
"mv_position": "{index} من {total}",
"plugin_panel_show": "إظهار لوحة الإضافة",
"plugin_panel_hide": "إخفاء لوحة الإضافة",
diff --git a/locales/ca/common.json b/locales/ca/common.json
index 5fd11fc39..011f70296 100644
--- a/locales/ca/common.json
+++ b/locales/ca/common.json
@@ -775,6 +775,69 @@
"copied": "Codi copiat",
"copy_failed": "No s'ha pogut copiar el codi"
},
+ "structured_mail": {
+ "kind_flight": "Vol",
+ "kind_train": "Tren",
+ "kind_bus": "Autobús",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Cotxe de lloguer",
+ "kind_event": "Esdeveniment",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Comanda",
+ "kind_parcel": "Paquet",
+ "region_flight": "Reserva de vol",
+ "region_train": "Reserva de tren",
+ "region_bus": "Reserva d'autobús",
+ "region_lodging": "Reserva d'hotel",
+ "region_rentalcar": "Reserva de cotxe de lloguer",
+ "region_event": "Reserva d'esdeveniment",
+ "region_restaurant": "Reserva de restaurant",
+ "region_shipment": "Comanda i lliurament",
+ "status_cancelled": "Cancel·lada",
+ "status_pending": "Pendent",
+ "status_hold": "En espera",
+ "order_status_payment_due": "Pagament pendent",
+ "order_status_processing": "En preparació",
+ "order_status_problem": "Problema",
+ "order_status_in_transit": "Enviada",
+ "order_status_pickup_available": "A punt per recollir",
+ "order_status_returned": "Retornada",
+ "order_status_delivered": "Lliurada",
+ "order_status_cancelled": "Cancel·lada",
+ "reference": "Codi de reserva",
+ "order_number": "Número de comanda",
+ "tracking_number": "Número de seguiment",
+ "copy_reference": "Copia el codi de reserva {value}",
+ "copy_order_number": "Copia el número de comanda {value}",
+ "copy_tracking_number": "Copia el número de seguiment {value}",
+ "copied_reference": "S'ha copiat el codi de reserva",
+ "copied_order_number": "S'ha copiat el número de comanda",
+ "copied_tracking_number": "S'ha copiat el número de seguiment",
+ "copy_failed": "No s'ha pogut copiar al porta-retalls",
+ "passengers": "Passatgers",
+ "seats": "Seients",
+ "tickets": "Entrades",
+ "link_check_in": "Facturació",
+ "link_manage": "Gestiona la reserva",
+ "link_ticket": "Entrada",
+ "link_track": "Segueix l'enviament",
+ "link_view_order": "Mostra la comanda",
+ "check_in_label": "Entrada",
+ "check_out_label": "Sortida",
+ "from_time": "des de les {time}",
+ "until_time": "fins a les {time}",
+ "nights": "{count, plural, one {# nit} other {# nits}}",
+ "pickup": "Recollida",
+ "dropoff": "Devolució",
+ "party_size": "{count, plural, one {Taula per a # persona} other {Taula per a # persones}}",
+ "items_more": "i {count} més",
+ "items_count": "{count, plural, one {# article} other {# articles}}",
+ "total": "Total {total}",
+ "expected_by": "Arriba abans del {date}",
+ "local_time": "hora local",
+ "local_time_title": "Hora local del lloc, no la de la teva zona horària",
+ "route": "{from} a {to}"
+ },
"mv_position": "{index} de {total}",
"plugin_panel_show": "Mostra el tauler del connector",
"plugin_panel_hide": "Amaga el tauler del connector",
diff --git a/locales/cs/common.json b/locales/cs/common.json
index 4312bdf79..f8142705c 100644
--- a/locales/cs/common.json
+++ b/locales/cs/common.json
@@ -775,6 +775,69 @@
"copied": "Kód zkopírován",
"copy_failed": "Kód se nepodařilo zkopírovat"
},
+ "structured_mail": {
+ "kind_flight": "Let",
+ "kind_train": "Vlak",
+ "kind_bus": "Autobus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Půjčené auto",
+ "kind_event": "Akce",
+ "kind_restaurant": "Restaurace",
+ "kind_order": "Objednávka",
+ "kind_parcel": "Zásilka",
+ "region_flight": "Rezervace letu",
+ "region_train": "Rezervace vlaku",
+ "region_bus": "Rezervace autobusu",
+ "region_lodging": "Rezervace hotelu",
+ "region_rentalcar": "Rezervace půjčeného auta",
+ "region_event": "Rezervace akce",
+ "region_restaurant": "Rezervace stolu",
+ "region_shipment": "Objednávka a doručení",
+ "status_cancelled": "Zrušeno",
+ "status_pending": "Čeká na potvrzení",
+ "status_hold": "Blokováno",
+ "order_status_payment_due": "Čeká na platbu",
+ "order_status_processing": "Zpracovává se",
+ "order_status_problem": "Problém",
+ "order_status_in_transit": "Odesláno",
+ "order_status_pickup_available": "Připraveno k vyzvednutí",
+ "order_status_returned": "Vráceno",
+ "order_status_delivered": "Doručeno",
+ "order_status_cancelled": "Zrušeno",
+ "reference": "Číslo rezervace",
+ "order_number": "Číslo objednávky",
+ "tracking_number": "Číslo zásilky",
+ "copy_reference": "Kopírovat číslo rezervace {value}",
+ "copy_order_number": "Kopírovat číslo objednávky {value}",
+ "copy_tracking_number": "Kopírovat číslo zásilky {value}",
+ "copied_reference": "Číslo rezervace zkopírováno",
+ "copied_order_number": "Číslo objednávky zkopírováno",
+ "copied_tracking_number": "Číslo zásilky zkopírováno",
+ "copy_failed": "Kopírování do schránky se nezdařilo",
+ "passengers": "Cestující",
+ "seats": "Místa",
+ "tickets": "Vstupenky",
+ "link_check_in": "Odbavit se",
+ "link_manage": "Spravovat rezervaci",
+ "link_ticket": "Vstupenka",
+ "link_track": "Sledovat",
+ "link_view_order": "Zobrazit objednávku",
+ "check_in_label": "Příjezd",
+ "check_out_label": "Odjezd",
+ "from_time": "od {time}",
+ "until_time": "do {time}",
+ "nights": "{count, plural, one {# noc} few {# noci} many {# noci} other {# nocí}}",
+ "pickup": "Vyzvednutí",
+ "dropoff": "Vrácení",
+ "party_size": "{count, plural, one {Stůl pro # osobu} few {Stůl pro # osoby} many {Stůl pro # osoby} other {Stůl pro # osob}}",
+ "items_more": "a {count} další",
+ "items_count": "{count, plural, one {# položka} few {# položky} many {# položky} other {# položek}}",
+ "total": "Celkem {total}",
+ "expected_by": "Doručení do {date}",
+ "local_time": "místní čas",
+ "local_time_title": "Místní čas na daném místě, ne ve vašem časovém pásmu",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} z {total}",
"plugin_panel_show": "Zobrazit panel pluginu",
"plugin_panel_hide": "Skrýt panel pluginu",
diff --git a/locales/da/common.json b/locales/da/common.json
index d2a51aabe..42abc69ce 100644
--- a/locales/da/common.json
+++ b/locales/da/common.json
@@ -775,6 +775,69 @@
"copied": "Kode kopieret",
"copy_failed": "Koden kunne ikke kopieres"
},
+ "structured_mail": {
+ "kind_flight": "Fly",
+ "kind_train": "Tog",
+ "kind_bus": "Bus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Lejebil",
+ "kind_event": "Begivenhed",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Ordre",
+ "kind_parcel": "Pakke",
+ "region_flight": "Flybooking",
+ "region_train": "Togbooking",
+ "region_bus": "Busbooking",
+ "region_lodging": "Hotelbooking",
+ "region_rentalcar": "Lejebilsbooking",
+ "region_event": "Begivenhedsbooking",
+ "region_restaurant": "Bordreservation",
+ "region_shipment": "Ordre og levering",
+ "status_cancelled": "Annulleret",
+ "status_pending": "Afventer",
+ "status_hold": "Reserveret",
+ "order_status_payment_due": "Betaling mangler",
+ "order_status_processing": "Behandles",
+ "order_status_problem": "Problem",
+ "order_status_in_transit": "Afsendt",
+ "order_status_pickup_available": "Klar til afhentning",
+ "order_status_returned": "Returneret",
+ "order_status_delivered": "Leveret",
+ "order_status_cancelled": "Annulleret",
+ "reference": "Bookingnummer",
+ "order_number": "Ordrenummer",
+ "tracking_number": "Sporingsnummer",
+ "copy_reference": "Kopiér bookingnummer {value}",
+ "copy_order_number": "Kopiér ordrenummer {value}",
+ "copy_tracking_number": "Kopiér sporingsnummer {value}",
+ "copied_reference": "Bookingnummer kopieret",
+ "copied_order_number": "Ordrenummer kopieret",
+ "copied_tracking_number": "Sporingsnummer kopieret",
+ "copy_failed": "Kunne ikke kopiere til udklipsholderen",
+ "passengers": "Rejsende",
+ "seats": "Pladser",
+ "tickets": "Billetter",
+ "link_check_in": "Check ind",
+ "link_manage": "Administrér booking",
+ "link_ticket": "Billet",
+ "link_track": "Spor",
+ "link_view_order": "Se ordre",
+ "check_in_label": "Indtjekning",
+ "check_out_label": "Udtjekning",
+ "from_time": "fra kl. {time}",
+ "until_time": "senest kl. {time}",
+ "nights": "{count, plural, one {# nat} other {# nætter}}",
+ "pickup": "Afhentning",
+ "dropoff": "Aflevering",
+ "party_size": "{count, plural, one {Bord til # person} other {Bord til # personer}}",
+ "items_more": "og {count} mere",
+ "items_count": "{count, plural, one {# vare} other {# varer}}",
+ "total": "I alt {total}",
+ "expected_by": "Ankommer senest {date}",
+ "local_time": "lokal tid",
+ "local_time_title": "Lokal tid på stedet, ikke din tidszone",
+ "route": "{from} til {to}"
+ },
"mv_position": "{index} af {total}",
"plugin_panel_show": "Vis pluginpanel",
"plugin_panel_hide": "Skjul pluginpanel",
diff --git a/locales/de/common.json b/locales/de/common.json
index 3d0b12f25..fb71f758c 100644
--- a/locales/de/common.json
+++ b/locales/de/common.json
@@ -775,6 +775,69 @@
"copied": "Code kopiert",
"copy_failed": "Code konnte nicht kopiert werden"
},
+ "structured_mail": {
+ "kind_flight": "Flug",
+ "kind_train": "Zug",
+ "kind_bus": "Bus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Mietwagen",
+ "kind_event": "Veranstaltung",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Bestellung",
+ "kind_parcel": "Paket",
+ "region_flight": "Flugbuchung",
+ "region_train": "Zugbuchung",
+ "region_bus": "Busbuchung",
+ "region_lodging": "Hotelbuchung",
+ "region_rentalcar": "Mietwagenbuchung",
+ "region_event": "Veranstaltungsbuchung",
+ "region_restaurant": "Tischreservierung",
+ "region_shipment": "Bestellung und Lieferung",
+ "status_cancelled": "Storniert",
+ "status_pending": "Ausstehend",
+ "status_hold": "Vorgemerkt",
+ "order_status_payment_due": "Zahlung ausstehend",
+ "order_status_processing": "In Bearbeitung",
+ "order_status_problem": "Problem",
+ "order_status_in_transit": "Versandt",
+ "order_status_pickup_available": "Abholbereit",
+ "order_status_returned": "Zurückgesendet",
+ "order_status_delivered": "Zugestellt",
+ "order_status_cancelled": "Storniert",
+ "reference": "Buchungsnummer",
+ "order_number": "Bestellnummer",
+ "tracking_number": "Sendungsnummer",
+ "copy_reference": "Buchungsnummer {value} kopieren",
+ "copy_order_number": "Bestellnummer {value} kopieren",
+ "copy_tracking_number": "Sendungsnummer {value} kopieren",
+ "copied_reference": "Buchungsnummer kopiert",
+ "copied_order_number": "Bestellnummer kopiert",
+ "copied_tracking_number": "Sendungsnummer kopiert",
+ "copy_failed": "Kopieren in die Zwischenablage fehlgeschlagen",
+ "passengers": "Reisende",
+ "seats": "Sitzplätze",
+ "tickets": "Tickets",
+ "link_check_in": "Einchecken",
+ "link_manage": "Buchung verwalten",
+ "link_ticket": "Ticket",
+ "link_track": "Verfolgen",
+ "link_view_order": "Bestellung ansehen",
+ "check_in_label": "Check-in",
+ "check_out_label": "Check-out",
+ "from_time": "ab {time}",
+ "until_time": "bis {time}",
+ "nights": "{count, plural, one {# Nacht} other {# Nächte}}",
+ "pickup": "Abholung",
+ "dropoff": "Rückgabe",
+ "party_size": "{count, plural, one {Tisch für # Person} other {Tisch für # Personen}}",
+ "items_more": "und {count} weitere",
+ "items_count": "{count, plural, one {# Artikel} other {# Artikel}}",
+ "total": "Gesamt {total}",
+ "expected_by": "Ankunft bis {date}",
+ "local_time": "Ortszeit",
+ "local_time_title": "Uhrzeit vor Ort, nicht in Ihrer Zeitzone",
+ "route": "{from} nach {to}"
+ },
"mv_position": "{index} von {total}",
"plugin_panel_show": "Plugin-Bereich einblenden",
"plugin_panel_hide": "Plugin-Bereich ausblenden",
diff --git a/locales/en/common.json b/locales/en/common.json
index ac2cef4e6..794a4ceae 100644
--- a/locales/en/common.json
+++ b/locales/en/common.json
@@ -775,6 +775,69 @@
"copied": "Code copied",
"copy_failed": "Could not copy the code"
},
+ "structured_mail": {
+ "kind_flight": "Flight",
+ "kind_train": "Train",
+ "kind_bus": "Bus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Rental car",
+ "kind_event": "Event",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Order",
+ "kind_parcel": "Parcel",
+ "region_flight": "Flight booking",
+ "region_train": "Train booking",
+ "region_bus": "Bus booking",
+ "region_lodging": "Hotel booking",
+ "region_rentalcar": "Rental car booking",
+ "region_event": "Event booking",
+ "region_restaurant": "Restaurant reservation",
+ "region_shipment": "Order and delivery",
+ "status_cancelled": "Cancelled",
+ "status_pending": "Pending",
+ "status_hold": "On hold",
+ "order_status_payment_due": "Payment due",
+ "order_status_processing": "Processing",
+ "order_status_problem": "Problem",
+ "order_status_in_transit": "Shipped",
+ "order_status_pickup_available": "Ready for pickup",
+ "order_status_returned": "Returned",
+ "order_status_delivered": "Delivered",
+ "order_status_cancelled": "Cancelled",
+ "reference": "Booking reference",
+ "order_number": "Order number",
+ "tracking_number": "Tracking number",
+ "copy_reference": "Copy booking reference {value}",
+ "copy_order_number": "Copy order number {value}",
+ "copy_tracking_number": "Copy tracking number {value}",
+ "copied_reference": "Booking reference copied",
+ "copied_order_number": "Order number copied",
+ "copied_tracking_number": "Tracking number copied",
+ "copy_failed": "Could not copy to the clipboard",
+ "passengers": "Passengers",
+ "seats": "Seats",
+ "tickets": "Tickets",
+ "link_check_in": "Check in",
+ "link_manage": "Manage booking",
+ "link_ticket": "Ticket",
+ "link_track": "Track",
+ "link_view_order": "View order",
+ "check_in_label": "Check-in",
+ "check_out_label": "Check-out",
+ "from_time": "from {time}",
+ "until_time": "until {time}",
+ "nights": "{count, plural, one {# night} other {# nights}}",
+ "pickup": "Pick-up",
+ "dropoff": "Return",
+ "party_size": "{count, plural, one {Table for #} other {Table for #}}",
+ "items_more": "and {count} more",
+ "items_count": "{count, plural, one {# item} other {# items}}",
+ "total": "Total {total}",
+ "expected_by": "Arrives by {date}",
+ "local_time": "local time",
+ "local_time_title": "Local time at the place, not your time zone",
+ "route": "{from} to {to}"
+ },
"mv_position": "{index} of {total}",
"copy": "Copy",
"contact_added": "Contact added",
diff --git a/locales/es/common.json b/locales/es/common.json
index d86594ef8..1f1c4dc57 100644
--- a/locales/es/common.json
+++ b/locales/es/common.json
@@ -775,6 +775,69 @@
"copied": "Código copiado",
"copy_failed": "No se pudo copiar el código"
},
+ "structured_mail": {
+ "kind_flight": "Vuelo",
+ "kind_train": "Tren",
+ "kind_bus": "Autobús",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Coche de alquiler",
+ "kind_event": "Evento",
+ "kind_restaurant": "Restaurante",
+ "kind_order": "Pedido",
+ "kind_parcel": "Paquete",
+ "region_flight": "Reserva de vuelo",
+ "region_train": "Reserva de tren",
+ "region_bus": "Reserva de autobús",
+ "region_lodging": "Reserva de hotel",
+ "region_rentalcar": "Reserva de coche de alquiler",
+ "region_event": "Reserva de evento",
+ "region_restaurant": "Reserva de restaurante",
+ "region_shipment": "Pedido y envío",
+ "status_cancelled": "Cancelada",
+ "status_pending": "Pendiente",
+ "status_hold": "En espera",
+ "order_status_payment_due": "Pago pendiente",
+ "order_status_processing": "En preparación",
+ "order_status_problem": "Problema",
+ "order_status_in_transit": "Enviado",
+ "order_status_pickup_available": "Listo para recoger",
+ "order_status_returned": "Devuelto",
+ "order_status_delivered": "Entregado",
+ "order_status_cancelled": "Cancelado",
+ "reference": "Código de reserva",
+ "order_number": "Número de pedido",
+ "tracking_number": "Número de seguimiento",
+ "copy_reference": "Copiar el código de reserva {value}",
+ "copy_order_number": "Copiar el número de pedido {value}",
+ "copy_tracking_number": "Copiar el número de seguimiento {value}",
+ "copied_reference": "Código de reserva copiado",
+ "copied_order_number": "Número de pedido copiado",
+ "copied_tracking_number": "Número de seguimiento copiado",
+ "copy_failed": "No se pudo copiar al portapapeles",
+ "passengers": "Pasajeros",
+ "seats": "Asientos",
+ "tickets": "Entradas",
+ "link_check_in": "Facturar",
+ "link_manage": "Gestionar reserva",
+ "link_ticket": "Entrada",
+ "link_track": "Seguir envío",
+ "link_view_order": "Ver pedido",
+ "check_in_label": "Entrada",
+ "check_out_label": "Salida",
+ "from_time": "desde las {time}",
+ "until_time": "hasta las {time}",
+ "nights": "{count, plural, one {# noche} other {# noches}}",
+ "pickup": "Recogida",
+ "dropoff": "Devolución",
+ "party_size": "{count, plural, one {Mesa para # persona} other {Mesa para # personas}}",
+ "items_more": "y {count} más",
+ "items_count": "{count, plural, one {# artículo} other {# artículos}}",
+ "total": "Total {total}",
+ "expected_by": "Llega antes del {date}",
+ "local_time": "hora local",
+ "local_time_title": "Hora local del lugar, no la de tu zona horaria",
+ "route": "{from} a {to}"
+ },
"mv_position": "{index} de {total}",
"plugin_panel_show": "Mostrar el panel del complemento",
"plugin_panel_hide": "Ocultar el panel del complemento",
diff --git a/locales/et/common.json b/locales/et/common.json
index 80c687eb0..2796ae65d 100644
--- a/locales/et/common.json
+++ b/locales/et/common.json
@@ -775,6 +775,69 @@
"copied": "Kood kopeeritud",
"copy_failed": "Koodi kopeerimine ebaõnnestus"
},
+ "structured_mail": {
+ "kind_flight": "Lend",
+ "kind_train": "Rong",
+ "kind_bus": "Buss",
+ "kind_lodging": "Hotell",
+ "kind_rentalcar": "Rendiauto",
+ "kind_event": "Üritus",
+ "kind_restaurant": "Restoran",
+ "kind_order": "Tellimus",
+ "kind_parcel": "Pakk",
+ "region_flight": "Lennubroneering",
+ "region_train": "Rongibroneering",
+ "region_bus": "Bussibroneering",
+ "region_lodging": "Hotellibroneering",
+ "region_rentalcar": "Rendiauto broneering",
+ "region_event": "Ürituse broneering",
+ "region_restaurant": "Lauabroneering",
+ "region_shipment": "Tellimus ja kohaletoimetamine",
+ "status_cancelled": "Tühistatud",
+ "status_pending": "Ootel",
+ "status_hold": "Reserveeritud",
+ "order_status_payment_due": "Makse ootel",
+ "order_status_processing": "Töötlemisel",
+ "order_status_problem": "Probleem",
+ "order_status_in_transit": "Saadetud",
+ "order_status_pickup_available": "Valmis kättesaamiseks",
+ "order_status_returned": "Tagastatud",
+ "order_status_delivered": "Kohale toimetatud",
+ "order_status_cancelled": "Tühistatud",
+ "reference": "Broneeringu number",
+ "order_number": "Tellimuse number",
+ "tracking_number": "Jälgimisnumber",
+ "copy_reference": "Kopeeri broneeringu number {value}",
+ "copy_order_number": "Kopeeri tellimuse number {value}",
+ "copy_tracking_number": "Kopeeri jälgimisnumber {value}",
+ "copied_reference": "Broneeringu number kopeeritud",
+ "copied_order_number": "Tellimuse number kopeeritud",
+ "copied_tracking_number": "Jälgimisnumber kopeeritud",
+ "copy_failed": "Lõikelauale kopeerimine ebaõnnestus",
+ "passengers": "Reisijad",
+ "seats": "Kohad",
+ "tickets": "Piletid",
+ "link_check_in": "Registreeru",
+ "link_manage": "Halda broneeringut",
+ "link_ticket": "Pilet",
+ "link_track": "Jälgi",
+ "link_view_order": "Vaata tellimust",
+ "check_in_label": "Sisseregistreerimine",
+ "check_out_label": "Väljaregistreerimine",
+ "from_time": "alates {time}",
+ "until_time": "kuni {time}",
+ "nights": "{count, plural, one {# öö} other {# ööd}}",
+ "pickup": "Kättesaamine",
+ "dropoff": "Tagastamine",
+ "party_size": "{count, plural, one {Laud # inimesele} other {Laud # inimesele}}",
+ "items_more": "ja veel {count}",
+ "items_count": "{count, plural, one {# toode} other {# toodet}}",
+ "total": "Kokku {total}",
+ "expected_by": "Saabub hiljemalt {date}",
+ "local_time": "kohalik aeg",
+ "local_time_title": "Kohalik aeg sihtkohas, mitte sinu ajavööndis",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} / {total}",
"plugin_panel_show": "Näita pistikprogrammi paneeli",
"plugin_panel_hide": "Peida pistikprogrammi paneel",
diff --git a/locales/fa/common.json b/locales/fa/common.json
index 9952d95f1..eb9c8e662 100644
--- a/locales/fa/common.json
+++ b/locales/fa/common.json
@@ -775,6 +775,69 @@
"copied": "کد کپی شد",
"copy_failed": "کپی کد ممکن نشد"
},
+ "structured_mail": {
+ "kind_flight": "پرواز",
+ "kind_train": "قطار",
+ "kind_bus": "اتوبوس",
+ "kind_lodging": "هتل",
+ "kind_rentalcar": "خودروی اجارهای",
+ "kind_event": "رویداد",
+ "kind_restaurant": "رستوران",
+ "kind_order": "سفارش",
+ "kind_parcel": "مرسوله",
+ "region_flight": "رزرو پرواز",
+ "region_train": "رزرو قطار",
+ "region_bus": "رزرو اتوبوس",
+ "region_lodging": "رزرو هتل",
+ "region_rentalcar": "رزرو خودروی اجارهای",
+ "region_event": "رزرو رویداد",
+ "region_restaurant": "رزرو رستوران",
+ "region_shipment": "سفارش و ارسال",
+ "status_cancelled": "لغو شده",
+ "status_pending": "در انتظار",
+ "status_hold": "نگهداشته شده",
+ "order_status_payment_due": "در انتظار پرداخت",
+ "order_status_processing": "در حال پردازش",
+ "order_status_problem": "مشکل",
+ "order_status_in_transit": "ارسال شده",
+ "order_status_pickup_available": "آماده تحویل",
+ "order_status_returned": "مرجوع شده",
+ "order_status_delivered": "تحویل داده شده",
+ "order_status_cancelled": "لغو شده",
+ "reference": "کد رزرو",
+ "order_number": "شماره سفارش",
+ "tracking_number": "کد رهگیری",
+ "copy_reference": "کپی کد رزرو {value}",
+ "copy_order_number": "کپی شماره سفارش {value}",
+ "copy_tracking_number": "کپی کد رهگیری {value}",
+ "copied_reference": "کد رزرو کپی شد",
+ "copied_order_number": "شماره سفارش کپی شد",
+ "copied_tracking_number": "کد رهگیری کپی شد",
+ "copy_failed": "کپی در کلیپبورد انجام نشد",
+ "passengers": "مسافران",
+ "seats": "صندلیها",
+ "tickets": "بلیتها",
+ "link_check_in": "پذیرش آنلاین",
+ "link_manage": "مدیریت رزرو",
+ "link_ticket": "بلیت",
+ "link_track": "رهگیری",
+ "link_view_order": "مشاهده سفارش",
+ "check_in_label": "ورود",
+ "check_out_label": "خروج",
+ "from_time": "از ساعت {time}",
+ "until_time": "تا ساعت {time}",
+ "nights": "{count, plural, one {# شب} other {# شب}}",
+ "pickup": "تحویل گرفتن",
+ "dropoff": "بازگرداندن",
+ "party_size": "{count, plural, one {میز برای # نفر} other {میز برای # نفر}}",
+ "items_more": "و {count} مورد دیگر",
+ "items_count": "{count, plural, one {# کالا} other {# کالا}}",
+ "total": "مجموع {total}",
+ "expected_by": "رسیدن تا {date}",
+ "local_time": "به وقت محلی",
+ "local_time_title": "به وقت محلی همان مکان، نه منطقه زمانی شما",
+ "route": "{from} به {to}"
+ },
"mv_position": "{index} از {total}",
"plugin_panel_show": "نمایش پنل افزونه",
"plugin_panel_hide": "پنهان کردن پنل افزونه",
diff --git a/locales/fr/common.json b/locales/fr/common.json
index 0b7c3ca2b..f1864ba6b 100644
--- a/locales/fr/common.json
+++ b/locales/fr/common.json
@@ -775,6 +775,69 @@
"copied": "Code copié",
"copy_failed": "Impossible de copier le code"
},
+ "structured_mail": {
+ "kind_flight": "Vol",
+ "kind_train": "Train",
+ "kind_bus": "Bus",
+ "kind_lodging": "Hôtel",
+ "kind_rentalcar": "Voiture de location",
+ "kind_event": "Événement",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Commande",
+ "kind_parcel": "Colis",
+ "region_flight": "Réservation de vol",
+ "region_train": "Réservation de train",
+ "region_bus": "Réservation de bus",
+ "region_lodging": "Réservation d'hôtel",
+ "region_rentalcar": "Location de voiture",
+ "region_event": "Réservation d'événement",
+ "region_restaurant": "Réservation de restaurant",
+ "region_shipment": "Commande et livraison",
+ "status_cancelled": "Annulée",
+ "status_pending": "En attente",
+ "status_hold": "Option",
+ "order_status_payment_due": "Paiement en attente",
+ "order_status_processing": "En préparation",
+ "order_status_problem": "Problème",
+ "order_status_in_transit": "Expédiée",
+ "order_status_pickup_available": "Prête à retirer",
+ "order_status_returned": "Retournée",
+ "order_status_delivered": "Livrée",
+ "order_status_cancelled": "Annulée",
+ "reference": "Référence de réservation",
+ "order_number": "Numéro de commande",
+ "tracking_number": "Numéro de suivi",
+ "copy_reference": "Copier la référence de réservation {value}",
+ "copy_order_number": "Copier le numéro de commande {value}",
+ "copy_tracking_number": "Copier le numéro de suivi {value}",
+ "copied_reference": "Référence de réservation copiée",
+ "copied_order_number": "Numéro de commande copié",
+ "copied_tracking_number": "Numéro de suivi copié",
+ "copy_failed": "Impossible de copier dans le presse-papiers",
+ "passengers": "Passagers",
+ "seats": "Places",
+ "tickets": "Billets",
+ "link_check_in": "Enregistrement",
+ "link_manage": "Gérer la réservation",
+ "link_ticket": "Billet",
+ "link_track": "Suivre",
+ "link_view_order": "Voir la commande",
+ "check_in_label": "Arrivée",
+ "check_out_label": "Départ",
+ "from_time": "à partir de {time}",
+ "until_time": "jusqu'à {time}",
+ "nights": "{count, plural, one {# nuit} other {# nuits}}",
+ "pickup": "Prise en charge",
+ "dropoff": "Restitution",
+ "party_size": "{count, plural, one {Table pour # personne} other {Table pour # personnes}}",
+ "items_more": "et {count} de plus",
+ "items_count": "{count, plural, one {# article} other {# articles}}",
+ "total": "Total {total}",
+ "expected_by": "Livraison prévue d'ici le {date}",
+ "local_time": "heure locale",
+ "local_time_title": "Heure locale du lieu, pas celle de votre fuseau horaire",
+ "route": "{from} vers {to}"
+ },
"mv_position": "{index} sur {total}",
"plugin_panel_show": "Afficher le panneau du plugin",
"plugin_panel_hide": "Masquer le panneau du plugin",
diff --git a/locales/he/common.json b/locales/he/common.json
index a2e191de9..4613cc593 100644
--- a/locales/he/common.json
+++ b/locales/he/common.json
@@ -740,6 +740,69 @@
"copied": "הקוד הועתק",
"copy_failed": "לא ניתן להעתיק את הקוד"
},
+ "structured_mail": {
+ "kind_flight": "טיסה",
+ "kind_train": "רכבת",
+ "kind_bus": "אוטובוס",
+ "kind_lodging": "מלון",
+ "kind_rentalcar": "רכב שכור",
+ "kind_event": "אירוע",
+ "kind_restaurant": "מסעדה",
+ "kind_order": "הזמנה",
+ "kind_parcel": "חבילה",
+ "region_flight": "הזמנת טיסה",
+ "region_train": "הזמנת רכבת",
+ "region_bus": "הזמנת אוטובוס",
+ "region_lodging": "הזמנת מלון",
+ "region_rentalcar": "הזמנת רכב שכור",
+ "region_event": "הזמנה לאירוע",
+ "region_restaurant": "הזמנת מקום במסעדה",
+ "region_shipment": "הזמנה ומשלוח",
+ "status_cancelled": "בוטלה",
+ "status_pending": "ממתינה",
+ "status_hold": "בהמתנה",
+ "order_status_payment_due": "ממתינה לתשלום",
+ "order_status_processing": "בטיפול",
+ "order_status_problem": "בעיה",
+ "order_status_in_transit": "נשלחה",
+ "order_status_pickup_available": "מוכנה לאיסוף",
+ "order_status_returned": "הוחזרה",
+ "order_status_delivered": "נמסרה",
+ "order_status_cancelled": "בוטלה",
+ "reference": "מספר הזמנה",
+ "order_number": "מספר הזמנה",
+ "tracking_number": "מספר מעקב",
+ "copy_reference": "העתקת מספר ההזמנה {value}",
+ "copy_order_number": "העתקת מספר ההזמנה {value}",
+ "copy_tracking_number": "העתקת מספר המעקב {value}",
+ "copied_reference": "מספר ההזמנה הועתק",
+ "copied_order_number": "מספר ההזמנה הועתק",
+ "copied_tracking_number": "מספר המעקב הועתק",
+ "copy_failed": "לא ניתן להעתיק ללוח",
+ "passengers": "נוסעים",
+ "seats": "מושבים",
+ "tickets": "כרטיסים",
+ "link_check_in": "צ'ק-אין",
+ "link_manage": "ניהול ההזמנה",
+ "link_ticket": "כרטיס",
+ "link_track": "מעקב",
+ "link_view_order": "הצגת ההזמנה",
+ "check_in_label": "צ'ק-אין",
+ "check_out_label": "צ'ק-אאוט",
+ "from_time": "החל מ-{time}",
+ "until_time": "עד {time}",
+ "nights": "{count, plural, one {לילה אחד} two {שני לילות} other {# לילות}}",
+ "pickup": "איסוף",
+ "dropoff": "החזרה",
+ "party_size": "{count, plural, one {שולחן לאדם אחד} other {שולחן ל-# אנשים}}",
+ "items_more": "ועוד {count}",
+ "items_count": "{count, plural, one {פריט אחד} other {# פריטים}}",
+ "total": "סה\"כ {total}",
+ "expected_by": "יגיע עד {date}",
+ "local_time": "שעון מקומי",
+ "local_time_title": "השעה המקומית במקום, לא באזור הזמן שלך",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} מתוך {total}",
"plugin_panel_show": "הצגת חלונית התוסף",
"plugin_panel_hide": "הסתרת חלונית התוסף",
diff --git a/locales/hu/common.json b/locales/hu/common.json
index dbe28e232..9ccb95bce 100644
--- a/locales/hu/common.json
+++ b/locales/hu/common.json
@@ -775,6 +775,69 @@
"copied": "Kód másolva",
"copy_failed": "Nem sikerült másolni a kódot"
},
+ "structured_mail": {
+ "kind_flight": "Repülőjárat",
+ "kind_train": "Vonat",
+ "kind_bus": "Busz",
+ "kind_lodging": "Szálloda",
+ "kind_rentalcar": "Bérautó",
+ "kind_event": "Esemény",
+ "kind_restaurant": "Étterem",
+ "kind_order": "Rendelés",
+ "kind_parcel": "Csomag",
+ "region_flight": "Repülőjegy-foglalás",
+ "region_train": "Vonatjegy-foglalás",
+ "region_bus": "Buszjegy-foglalás",
+ "region_lodging": "Szállásfoglalás",
+ "region_rentalcar": "Bérautó-foglalás",
+ "region_event": "Eseményfoglalás",
+ "region_restaurant": "Asztalfoglalás",
+ "region_shipment": "Rendelés és szállítás",
+ "status_cancelled": "Lemondva",
+ "status_pending": "Függőben",
+ "status_hold": "Előfoglalva",
+ "order_status_payment_due": "Fizetésre vár",
+ "order_status_processing": "Feldolgozás alatt",
+ "order_status_problem": "Probléma",
+ "order_status_in_transit": "Feladva",
+ "order_status_pickup_available": "Átvehető",
+ "order_status_returned": "Visszaküldve",
+ "order_status_delivered": "Kézbesítve",
+ "order_status_cancelled": "Lemondva",
+ "reference": "Foglalási szám",
+ "order_number": "Rendelésszám",
+ "tracking_number": "Követési szám",
+ "copy_reference": "{value} foglalási szám másolása",
+ "copy_order_number": "{value} rendelésszám másolása",
+ "copy_tracking_number": "{value} követési szám másolása",
+ "copied_reference": "Foglalási szám másolva",
+ "copied_order_number": "Rendelésszám másolva",
+ "copied_tracking_number": "Követési szám másolva",
+ "copy_failed": "Nem sikerült a vágólapra másolni",
+ "passengers": "Utasok",
+ "seats": "Ülőhelyek",
+ "tickets": "Jegyek",
+ "link_check_in": "Utasfelvétel",
+ "link_manage": "Foglalás kezelése",
+ "link_ticket": "Jegy",
+ "link_track": "Követés",
+ "link_view_order": "Rendelés megtekintése",
+ "check_in_label": "Bejelentkezés",
+ "check_out_label": "Kijelentkezés",
+ "from_time": "{time}-tól",
+ "until_time": "{time}-ig",
+ "nights": "{count, plural, one {# éjszaka} other {# éjszaka}}",
+ "pickup": "Átvétel",
+ "dropoff": "Leadás",
+ "party_size": "{count, plural, one {Asztal # főre} other {Asztal # főre}}",
+ "items_more": "és még {count}",
+ "items_count": "{count, plural, one {# tétel} other {# tétel}}",
+ "total": "Összesen {total}",
+ "expected_by": "Érkezés legkésőbb: {date}",
+ "local_time": "helyi idő",
+ "local_time_title": "Az adott hely helyi ideje, nem a saját időzónád",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} / {total}",
"plugin_panel_show": "Bővítménypanel megjelenítése",
"plugin_panel_hide": "Bővítménypanel elrejtése",
diff --git a/locales/it/common.json b/locales/it/common.json
index 7a4063840..e773253db 100644
--- a/locales/it/common.json
+++ b/locales/it/common.json
@@ -775,6 +775,69 @@
"copied": "Codice copiato",
"copy_failed": "Impossibile copiare il codice"
},
+ "structured_mail": {
+ "kind_flight": "Volo",
+ "kind_train": "Treno",
+ "kind_bus": "Autobus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Auto a noleggio",
+ "kind_event": "Evento",
+ "kind_restaurant": "Ristorante",
+ "kind_order": "Ordine",
+ "kind_parcel": "Pacco",
+ "region_flight": "Prenotazione volo",
+ "region_train": "Prenotazione treno",
+ "region_bus": "Prenotazione autobus",
+ "region_lodging": "Prenotazione hotel",
+ "region_rentalcar": "Noleggio auto",
+ "region_event": "Prenotazione evento",
+ "region_restaurant": "Prenotazione ristorante",
+ "region_shipment": "Ordine e consegna",
+ "status_cancelled": "Cancellata",
+ "status_pending": "In attesa",
+ "status_hold": "Opzionata",
+ "order_status_payment_due": "Pagamento in sospeso",
+ "order_status_processing": "In lavorazione",
+ "order_status_problem": "Problema",
+ "order_status_in_transit": "Spedito",
+ "order_status_pickup_available": "Pronto per il ritiro",
+ "order_status_returned": "Reso",
+ "order_status_delivered": "Consegnato",
+ "order_status_cancelled": "Annullato",
+ "reference": "Codice di prenotazione",
+ "order_number": "Numero d'ordine",
+ "tracking_number": "Numero di tracciamento",
+ "copy_reference": "Copia il codice di prenotazione {value}",
+ "copy_order_number": "Copia il numero d'ordine {value}",
+ "copy_tracking_number": "Copia il numero di tracciamento {value}",
+ "copied_reference": "Codice di prenotazione copiato",
+ "copied_order_number": "Numero d'ordine copiato",
+ "copied_tracking_number": "Numero di tracciamento copiato",
+ "copy_failed": "Impossibile copiare negli appunti",
+ "passengers": "Passeggeri",
+ "seats": "Posti",
+ "tickets": "Biglietti",
+ "link_check_in": "Check-in",
+ "link_manage": "Gestisci prenotazione",
+ "link_ticket": "Biglietto",
+ "link_track": "Traccia",
+ "link_view_order": "Vedi ordine",
+ "check_in_label": "Check-in",
+ "check_out_label": "Check-out",
+ "from_time": "dalle {time}",
+ "until_time": "entro le {time}",
+ "nights": "{count, plural, one {# notte} other {# notti}}",
+ "pickup": "Ritiro",
+ "dropoff": "Riconsegna",
+ "party_size": "{count, plural, one {Tavolo per # persona} other {Tavolo per # persone}}",
+ "items_more": "e altri {count}",
+ "items_count": "{count, plural, one {# articolo} other {# articoli}}",
+ "total": "Totale {total}",
+ "expected_by": "Arriva entro {date}",
+ "local_time": "ora locale",
+ "local_time_title": "Ora locale del luogo, non del tuo fuso orario",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} di {total}",
"plugin_panel_show": "Mostra il pannello del plugin",
"plugin_panel_hide": "Nascondi il pannello del plugin",
diff --git a/locales/ja/common.json b/locales/ja/common.json
index 8eff3d2ce..3de4341b6 100644
--- a/locales/ja/common.json
+++ b/locales/ja/common.json
@@ -775,6 +775,69 @@
"copied": "コードをコピーしました",
"copy_failed": "コードをコピーできませんでした"
},
+ "structured_mail": {
+ "kind_flight": "フライト",
+ "kind_train": "列車",
+ "kind_bus": "バス",
+ "kind_lodging": "ホテル",
+ "kind_rentalcar": "レンタカー",
+ "kind_event": "イベント",
+ "kind_restaurant": "レストラン",
+ "kind_order": "注文",
+ "kind_parcel": "荷物",
+ "region_flight": "フライトの予約",
+ "region_train": "列車の予約",
+ "region_bus": "バスの予約",
+ "region_lodging": "ホテルの予約",
+ "region_rentalcar": "レンタカーの予約",
+ "region_event": "イベントの予約",
+ "region_restaurant": "レストランの予約",
+ "region_shipment": "注文と配送",
+ "status_cancelled": "キャンセル済み",
+ "status_pending": "保留中",
+ "status_hold": "仮押さえ",
+ "order_status_payment_due": "支払い待ち",
+ "order_status_processing": "準備中",
+ "order_status_problem": "問題あり",
+ "order_status_in_transit": "発送済み",
+ "order_status_pickup_available": "受け取り可能",
+ "order_status_returned": "返品済み",
+ "order_status_delivered": "配達済み",
+ "order_status_cancelled": "キャンセル済み",
+ "reference": "予約番号",
+ "order_number": "注文番号",
+ "tracking_number": "追跡番号",
+ "copy_reference": "予約番号 {value} をコピー",
+ "copy_order_number": "注文番号 {value} をコピー",
+ "copy_tracking_number": "追跡番号 {value} をコピー",
+ "copied_reference": "予約番号をコピーしました",
+ "copied_order_number": "注文番号をコピーしました",
+ "copied_tracking_number": "追跡番号をコピーしました",
+ "copy_failed": "クリップボードにコピーできませんでした",
+ "passengers": "搭乗者",
+ "seats": "座席",
+ "tickets": "チケット",
+ "link_check_in": "チェックイン",
+ "link_manage": "予約を管理",
+ "link_ticket": "チケット",
+ "link_track": "追跡",
+ "link_view_order": "注文を表示",
+ "check_in_label": "チェックイン",
+ "check_out_label": "チェックアウト",
+ "from_time": "{time}以降",
+ "until_time": "{time}まで",
+ "nights": "{count, plural, other {#泊}}",
+ "pickup": "貸出",
+ "dropoff": "返却",
+ "party_size": "{count, plural, other {#名様}}",
+ "items_more": "ほか{count}点",
+ "items_count": "{count, plural, other {#点}}",
+ "total": "合計 {total}",
+ "expected_by": "{date}までにお届け予定",
+ "local_time": "現地時間",
+ "local_time_title": "あなたのタイムゾーンではなく、その場所の現地時間です",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} / {total}",
"plugin_panel_show": "プラグインパネルを表示",
"plugin_panel_hide": "プラグインパネルを隠す",
diff --git a/locales/ko/common.json b/locales/ko/common.json
index c39ef6888..e162dfe8d 100644
--- a/locales/ko/common.json
+++ b/locales/ko/common.json
@@ -775,6 +775,69 @@
"copied": "코드를 복사했습니다",
"copy_failed": "코드를 복사할 수 없습니다"
},
+ "structured_mail": {
+ "kind_flight": "항공편",
+ "kind_train": "기차",
+ "kind_bus": "버스",
+ "kind_lodging": "호텔",
+ "kind_rentalcar": "렌터카",
+ "kind_event": "이벤트",
+ "kind_restaurant": "레스토랑",
+ "kind_order": "주문",
+ "kind_parcel": "택배",
+ "region_flight": "항공편 예약",
+ "region_train": "기차 예약",
+ "region_bus": "버스 예약",
+ "region_lodging": "호텔 예약",
+ "region_rentalcar": "렌터카 예약",
+ "region_event": "이벤트 예약",
+ "region_restaurant": "레스토랑 예약",
+ "region_shipment": "주문 및 배송",
+ "status_cancelled": "취소됨",
+ "status_pending": "대기 중",
+ "status_hold": "임시 예약",
+ "order_status_payment_due": "결제 대기",
+ "order_status_processing": "처리 중",
+ "order_status_problem": "문제 발생",
+ "order_status_in_transit": "발송됨",
+ "order_status_pickup_available": "수령 가능",
+ "order_status_returned": "반품됨",
+ "order_status_delivered": "배송 완료",
+ "order_status_cancelled": "취소됨",
+ "reference": "예약 번호",
+ "order_number": "주문 번호",
+ "tracking_number": "운송장 번호",
+ "copy_reference": "예약 번호 {value} 복사",
+ "copy_order_number": "주문 번호 {value} 복사",
+ "copy_tracking_number": "운송장 번호 {value} 복사",
+ "copied_reference": "예약 번호를 복사했습니다",
+ "copied_order_number": "주문 번호를 복사했습니다",
+ "copied_tracking_number": "운송장 번호를 복사했습니다",
+ "copy_failed": "클립보드에 복사하지 못했습니다",
+ "passengers": "탑승객",
+ "seats": "좌석",
+ "tickets": "티켓",
+ "link_check_in": "체크인",
+ "link_manage": "예약 관리",
+ "link_ticket": "티켓",
+ "link_track": "배송 조회",
+ "link_view_order": "주문 보기",
+ "check_in_label": "체크인",
+ "check_out_label": "체크아웃",
+ "from_time": "{time}부터",
+ "until_time": "{time}까지",
+ "nights": "{count, plural, other {#박}}",
+ "pickup": "인수",
+ "dropoff": "반납",
+ "party_size": "{count, plural, other {#명 테이블}}",
+ "items_more": "외 {count}개",
+ "items_count": "{count, plural, other {상품 #개}}",
+ "total": "합계 {total}",
+ "expected_by": "{date}까지 도착 예정",
+ "local_time": "현지 시간",
+ "local_time_title": "사용자의 시간대가 아닌 해당 장소의 현지 시간입니다",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} / {total}",
"plugin_panel_show": "플러그인 패널 표시",
"plugin_panel_hide": "플러그인 패널 숨기기",
diff --git a/locales/lv/common.json b/locales/lv/common.json
index 3e306355d..6b791f8d3 100644
--- a/locales/lv/common.json
+++ b/locales/lv/common.json
@@ -775,6 +775,69 @@
"copied": "Kods nokopēts",
"copy_failed": "Neizdevās nokopēt kodu"
},
+ "structured_mail": {
+ "kind_flight": "Lidojums",
+ "kind_train": "Vilciens",
+ "kind_bus": "Autobuss",
+ "kind_lodging": "Viesnīca",
+ "kind_rentalcar": "Nomas auto",
+ "kind_event": "Pasākums",
+ "kind_restaurant": "Restorāns",
+ "kind_order": "Pasūtījums",
+ "kind_parcel": "Sūtījums",
+ "region_flight": "Lidojuma rezervācija",
+ "region_train": "Vilciena rezervācija",
+ "region_bus": "Autobusa rezervācija",
+ "region_lodging": "Viesnīcas rezervācija",
+ "region_rentalcar": "Nomas auto rezervācija",
+ "region_event": "Pasākuma rezervācija",
+ "region_restaurant": "Galdiņa rezervācija",
+ "region_shipment": "Pasūtījums un piegāde",
+ "status_cancelled": "Atcelts",
+ "status_pending": "Gaida apstiprinājumu",
+ "status_hold": "Rezervēts",
+ "order_status_payment_due": "Gaida apmaksu",
+ "order_status_processing": "Tiek apstrādāts",
+ "order_status_problem": "Problēma",
+ "order_status_in_transit": "Nosūtīts",
+ "order_status_pickup_available": "Gatavs saņemšanai",
+ "order_status_returned": "Atgriezts",
+ "order_status_delivered": "Piegādāts",
+ "order_status_cancelled": "Atcelts",
+ "reference": "Rezervācijas numurs",
+ "order_number": "Pasūtījuma numurs",
+ "tracking_number": "Izsekošanas numurs",
+ "copy_reference": "Kopēt rezervācijas numuru {value}",
+ "copy_order_number": "Kopēt pasūtījuma numuru {value}",
+ "copy_tracking_number": "Kopēt izsekošanas numuru {value}",
+ "copied_reference": "Rezervācijas numurs nokopēts",
+ "copied_order_number": "Pasūtījuma numurs nokopēts",
+ "copied_tracking_number": "Izsekošanas numurs nokopēts",
+ "copy_failed": "Neizdevās nokopēt starpliktuvē",
+ "passengers": "Pasažieri",
+ "seats": "Vietas",
+ "tickets": "Biļetes",
+ "link_check_in": "Reģistrēties",
+ "link_manage": "Pārvaldīt rezervāciju",
+ "link_ticket": "Biļete",
+ "link_track": "Izsekot",
+ "link_view_order": "Skatīt pasūtījumu",
+ "check_in_label": "Reģistrēšanās",
+ "check_out_label": "Izrakstīšanās",
+ "from_time": "no {time}",
+ "until_time": "līdz {time}",
+ "nights": "{count, plural, zero {# naktis} one {# nakts} other {# naktis}}",
+ "pickup": "Saņemšana",
+ "dropoff": "Nodošana",
+ "party_size": "{count, plural, zero {Galdiņš # personām} one {Galdiņš # personai} other {Galdiņš # personām}}",
+ "items_more": "un vēl {count}",
+ "items_count": "{count, plural, zero {# preču} one {# prece} other {# preces}}",
+ "total": "Kopā {total}",
+ "expected_by": "Piegāde līdz {date}",
+ "local_time": "vietējais laiks",
+ "local_time_title": "Vietējais laiks attiecīgajā vietā, nevis jūsu laika joslā",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} no {total}",
"plugin_panel_show": "Rādīt spraudņa paneli",
"plugin_panel_hide": "Slēpt spraudņa paneli",
diff --git a/locales/mn/common.json b/locales/mn/common.json
index a4b8666a7..8424ca6b9 100644
--- a/locales/mn/common.json
+++ b/locales/mn/common.json
@@ -775,6 +775,69 @@
"copied": "Код хуулагдлаа",
"copy_failed": "Кодыг хуулж чадсангүй"
},
+ "structured_mail": {
+ "kind_flight": "Нислэг",
+ "kind_train": "Галт тэрэг",
+ "kind_bus": "Автобус",
+ "kind_lodging": "Зочид буудал",
+ "kind_rentalcar": "Түрээсийн машин",
+ "kind_event": "Арга хэмжээ",
+ "kind_restaurant": "Ресторан",
+ "kind_order": "Захиалга",
+ "kind_parcel": "Илгээмж",
+ "region_flight": "Нислэгийн захиалга",
+ "region_train": "Галт тэрэгний захиалга",
+ "region_bus": "Автобусны захиалга",
+ "region_lodging": "Зочид буудлын захиалга",
+ "region_rentalcar": "Түрээсийн машины захиалга",
+ "region_event": "Арга хэмжээний захиалга",
+ "region_restaurant": "Ширээний захиалга",
+ "region_shipment": "Захиалга ба хүргэлт",
+ "status_cancelled": "Цуцлагдсан",
+ "status_pending": "Хүлээгдэж байна",
+ "status_hold": "Түр барьсан",
+ "order_status_payment_due": "Төлбөр хүлээгдэж байна",
+ "order_status_processing": "Боловсруулж байна",
+ "order_status_problem": "Асуудалтай",
+ "order_status_in_transit": "Илгээсэн",
+ "order_status_pickup_available": "Авахад бэлэн",
+ "order_status_returned": "Буцаасан",
+ "order_status_delivered": "Хүргэгдсэн",
+ "order_status_cancelled": "Цуцлагдсан",
+ "reference": "Захиалгын код",
+ "order_number": "Захиалгын дугаар",
+ "tracking_number": "Мөрдөх дугаар",
+ "copy_reference": "Захиалгын код {value}-г хуулах",
+ "copy_order_number": "Захиалгын дугаар {value}-г хуулах",
+ "copy_tracking_number": "Мөрдөх дугаар {value}-г хуулах",
+ "copied_reference": "Захиалгын кодыг хуулсан",
+ "copied_order_number": "Захиалгын дугаарыг хуулсан",
+ "copied_tracking_number": "Мөрдөх дугаарыг хуулсан",
+ "copy_failed": "Санах ой руу хуулж чадсангүй",
+ "passengers": "Зорчигчид",
+ "seats": "Суудал",
+ "tickets": "Тасалбар",
+ "link_check_in": "Бүртгүүлэх",
+ "link_manage": "Захиалга удирдах",
+ "link_ticket": "Тасалбар",
+ "link_track": "Мөрдөх",
+ "link_view_order": "Захиалга харах",
+ "check_in_label": "Буудалд орох",
+ "check_out_label": "Буудлаас гарах",
+ "from_time": "{time}-аас",
+ "until_time": "{time} хүртэл",
+ "nights": "{count, plural, one {# шөнө} other {# шөнө}}",
+ "pickup": "Авах",
+ "dropoff": "Буцаах",
+ "party_size": "{count, plural, one {# хүний ширээ} other {# хүний ширээ}}",
+ "items_more": "болон өөр {count}",
+ "items_count": "{count, plural, one {# бараа} other {# бараа}}",
+ "total": "Нийт {total}",
+ "expected_by": "{date}-ны дотор ирнэ",
+ "local_time": "орон нутгийн цаг",
+ "local_time_title": "Тухайн газрын орон нутгийн цаг, таны цагийн бүс биш",
+ "route": "{from} – {to}"
+ },
"mv_position": "{total}-с {index}",
"plugin_panel_show": "Залгаасын самбарыг харуулах",
"plugin_panel_hide": "Залгаасын самбарыг нуух",
diff --git a/locales/nb/common.json b/locales/nb/common.json
index f205d3a22..02c12350a 100644
--- a/locales/nb/common.json
+++ b/locales/nb/common.json
@@ -775,6 +775,69 @@
"copied": "Kode kopiert",
"copy_failed": "Kunne ikke kopiere koden"
},
+ "structured_mail": {
+ "kind_flight": "Fly",
+ "kind_train": "Tog",
+ "kind_bus": "Buss",
+ "kind_lodging": "Hotell",
+ "kind_rentalcar": "Leiebil",
+ "kind_event": "Arrangement",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Bestilling",
+ "kind_parcel": "Pakke",
+ "region_flight": "Flybestilling",
+ "region_train": "Togbestilling",
+ "region_bus": "Bussbestilling",
+ "region_lodging": "Hotellbestilling",
+ "region_rentalcar": "Leiebilbestilling",
+ "region_event": "Arrangementsbestilling",
+ "region_restaurant": "Bordreservasjon",
+ "region_shipment": "Bestilling og levering",
+ "status_cancelled": "Kansellert",
+ "status_pending": "Venter",
+ "status_hold": "Reservert",
+ "order_status_payment_due": "Betaling mangler",
+ "order_status_processing": "Behandles",
+ "order_status_problem": "Problem",
+ "order_status_in_transit": "Sendt",
+ "order_status_pickup_available": "Klar til henting",
+ "order_status_returned": "Returnert",
+ "order_status_delivered": "Levert",
+ "order_status_cancelled": "Kansellert",
+ "reference": "Bestillingsnummer",
+ "order_number": "Ordrenummer",
+ "tracking_number": "Sporingsnummer",
+ "copy_reference": "Kopier bestillingsnummer {value}",
+ "copy_order_number": "Kopier ordrenummer {value}",
+ "copy_tracking_number": "Kopier sporingsnummer {value}",
+ "copied_reference": "Bestillingsnummer kopiert",
+ "copied_order_number": "Ordrenummer kopiert",
+ "copied_tracking_number": "Sporingsnummer kopiert",
+ "copy_failed": "Kunne ikke kopiere til utklippstavlen",
+ "passengers": "Reisende",
+ "seats": "Seter",
+ "tickets": "Billetter",
+ "link_check_in": "Sjekk inn",
+ "link_manage": "Administrer bestilling",
+ "link_ticket": "Billett",
+ "link_track": "Spor",
+ "link_view_order": "Vis bestilling",
+ "check_in_label": "Innsjekking",
+ "check_out_label": "Utsjekking",
+ "from_time": "fra kl. {time}",
+ "until_time": "innen kl. {time}",
+ "nights": "{count, plural, one {# natt} other {# netter}}",
+ "pickup": "Henting",
+ "dropoff": "Innlevering",
+ "party_size": "{count, plural, one {Bord for # person} other {Bord for # personer}}",
+ "items_more": "og {count} til",
+ "items_count": "{count, plural, one {# vare} other {# varer}}",
+ "total": "Totalt {total}",
+ "expected_by": "Kommer innen {date}",
+ "local_time": "lokal tid",
+ "local_time_title": "Lokal tid på stedet, ikke din tidssone",
+ "route": "{from} til {to}"
+ },
"mv_position": "{index} av {total}",
"plugin_panel_show": "Vis tilleggspanel",
"plugin_panel_hide": "Skjul tilleggspanel",
diff --git a/locales/nl/common.json b/locales/nl/common.json
index 83bb922d8..328683689 100644
--- a/locales/nl/common.json
+++ b/locales/nl/common.json
@@ -775,6 +775,69 @@
"copied": "Code gekopieerd",
"copy_failed": "Kan de code niet kopiëren"
},
+ "structured_mail": {
+ "kind_flight": "Vlucht",
+ "kind_train": "Trein",
+ "kind_bus": "Bus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Huurauto",
+ "kind_event": "Evenement",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Bestelling",
+ "kind_parcel": "Pakket",
+ "region_flight": "Vluchtboeking",
+ "region_train": "Treinboeking",
+ "region_bus": "Busboeking",
+ "region_lodging": "Hotelboeking",
+ "region_rentalcar": "Huurautoboeking",
+ "region_event": "Evenementboeking",
+ "region_restaurant": "Restaurantreservering",
+ "region_shipment": "Bestelling en levering",
+ "status_cancelled": "Geannuleerd",
+ "status_pending": "In behandeling",
+ "status_hold": "In optie",
+ "order_status_payment_due": "Betaling open",
+ "order_status_processing": "Wordt verwerkt",
+ "order_status_problem": "Probleem",
+ "order_status_in_transit": "Verzonden",
+ "order_status_pickup_available": "Klaar om op te halen",
+ "order_status_returned": "Geretourneerd",
+ "order_status_delivered": "Bezorgd",
+ "order_status_cancelled": "Geannuleerd",
+ "reference": "Boekingsnummer",
+ "order_number": "Bestelnummer",
+ "tracking_number": "Trackingnummer",
+ "copy_reference": "Boekingsnummer {value} kopiëren",
+ "copy_order_number": "Bestelnummer {value} kopiëren",
+ "copy_tracking_number": "Trackingnummer {value} kopiëren",
+ "copied_reference": "Boekingsnummer gekopieerd",
+ "copied_order_number": "Bestelnummer gekopieerd",
+ "copied_tracking_number": "Trackingnummer gekopieerd",
+ "copy_failed": "Kopiëren naar het klembord is mislukt",
+ "passengers": "Reizigers",
+ "seats": "Stoelen",
+ "tickets": "Tickets",
+ "link_check_in": "Inchecken",
+ "link_manage": "Boeking beheren",
+ "link_ticket": "Ticket",
+ "link_track": "Volgen",
+ "link_view_order": "Bestelling bekijken",
+ "check_in_label": "Inchecken",
+ "check_out_label": "Uitchecken",
+ "from_time": "vanaf {time}",
+ "until_time": "tot {time}",
+ "nights": "{count, plural, one {# nacht} other {# nachten}}",
+ "pickup": "Ophalen",
+ "dropoff": "Inleveren",
+ "party_size": "{count, plural, one {Tafel voor # persoon} other {Tafel voor # personen}}",
+ "items_more": "en nog {count}",
+ "items_count": "{count, plural, one {# artikel} other {# artikelen}}",
+ "total": "Totaal {total}",
+ "expected_by": "Verwacht uiterlijk {date}",
+ "local_time": "lokale tijd",
+ "local_time_title": "Lokale tijd ter plaatse, niet in je eigen tijdzone",
+ "route": "{from} naar {to}"
+ },
"mv_position": "{index} van {total}",
"plugin_panel_show": "Plug-inpaneel tonen",
"plugin_panel_hide": "Plug-inpaneel verbergen",
diff --git a/locales/pl/common.json b/locales/pl/common.json
index ca617443d..34098e164 100644
--- a/locales/pl/common.json
+++ b/locales/pl/common.json
@@ -775,6 +775,69 @@
"copied": "Skopiowano kod",
"copy_failed": "Nie udało się skopiować kodu"
},
+ "structured_mail": {
+ "kind_flight": "Lot",
+ "kind_train": "Pociąg",
+ "kind_bus": "Autobus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Wynajem samochodu",
+ "kind_event": "Wydarzenie",
+ "kind_restaurant": "Restauracja",
+ "kind_order": "Zamówienie",
+ "kind_parcel": "Przesyłka",
+ "region_flight": "Rezerwacja lotu",
+ "region_train": "Rezerwacja pociągu",
+ "region_bus": "Rezerwacja autobusu",
+ "region_lodging": "Rezerwacja hotelu",
+ "region_rentalcar": "Rezerwacja samochodu",
+ "region_event": "Rezerwacja wydarzenia",
+ "region_restaurant": "Rezerwacja stolika",
+ "region_shipment": "Zamówienie i dostawa",
+ "status_cancelled": "Anulowano",
+ "status_pending": "Oczekuje",
+ "status_hold": "Wstępna rezerwacja",
+ "order_status_payment_due": "Oczekuje na płatność",
+ "order_status_processing": "W realizacji",
+ "order_status_problem": "Problem",
+ "order_status_in_transit": "Wysłano",
+ "order_status_pickup_available": "Gotowe do odbioru",
+ "order_status_returned": "Zwrócono",
+ "order_status_delivered": "Dostarczono",
+ "order_status_cancelled": "Anulowano",
+ "reference": "Numer rezerwacji",
+ "order_number": "Numer zamówienia",
+ "tracking_number": "Numer przesyłki",
+ "copy_reference": "Kopiuj numer rezerwacji {value}",
+ "copy_order_number": "Kopiuj numer zamówienia {value}",
+ "copy_tracking_number": "Kopiuj numer przesyłki {value}",
+ "copied_reference": "Skopiowano numer rezerwacji",
+ "copied_order_number": "Skopiowano numer zamówienia",
+ "copied_tracking_number": "Skopiowano numer przesyłki",
+ "copy_failed": "Nie udało się skopiować do schowka",
+ "passengers": "Pasażerowie",
+ "seats": "Miejsca",
+ "tickets": "Bilety",
+ "link_check_in": "Odprawa",
+ "link_manage": "Zarządzaj rezerwacją",
+ "link_ticket": "Bilet",
+ "link_track": "Śledź",
+ "link_view_order": "Pokaż zamówienie",
+ "check_in_label": "Zameldowanie",
+ "check_out_label": "Wymeldowanie",
+ "from_time": "od {time}",
+ "until_time": "do {time}",
+ "nights": "{count, plural, one {# noc} few {# noce} many {# nocy} other {# nocy}}",
+ "pickup": "Odbiór",
+ "dropoff": "Zwrot",
+ "party_size": "{count, plural, one {Stolik dla # osoby} few {Stolik dla # osób} many {Stolik dla # osób} other {Stolik dla # osoby}}",
+ "items_more": "i {count} więcej",
+ "items_count": "{count, plural, one {# produkt} few {# produkty} many {# produktów} other {# produktu}}",
+ "total": "Razem {total}",
+ "expected_by": "Dostawa do {date}",
+ "local_time": "czas lokalny",
+ "local_time_title": "Czas lokalny w danym miejscu, nie w Twojej strefie czasowej",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} z {total}",
"plugin_panel_show": "Pokaż panel wtyczki",
"plugin_panel_hide": "Ukryj panel wtyczki",
diff --git a/locales/pt/common.json b/locales/pt/common.json
index bdbf61dc3..e34121053 100644
--- a/locales/pt/common.json
+++ b/locales/pt/common.json
@@ -775,6 +775,69 @@
"copied": "Código copiado",
"copy_failed": "Não foi possível copiar o código"
},
+ "structured_mail": {
+ "kind_flight": "Voo",
+ "kind_train": "Comboio",
+ "kind_bus": "Autocarro",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Carro alugado",
+ "kind_event": "Evento",
+ "kind_restaurant": "Restaurante",
+ "kind_order": "Encomenda",
+ "kind_parcel": "Encomenda postal",
+ "region_flight": "Reserva de voo",
+ "region_train": "Reserva de comboio",
+ "region_bus": "Reserva de autocarro",
+ "region_lodging": "Reserva de hotel",
+ "region_rentalcar": "Reserva de carro alugado",
+ "region_event": "Reserva de evento",
+ "region_restaurant": "Reserva de restaurante",
+ "region_shipment": "Encomenda e entrega",
+ "status_cancelled": "Cancelada",
+ "status_pending": "Pendente",
+ "status_hold": "Em espera",
+ "order_status_payment_due": "Pagamento pendente",
+ "order_status_processing": "Em preparação",
+ "order_status_problem": "Problema",
+ "order_status_in_transit": "Enviada",
+ "order_status_pickup_available": "Pronta para levantar",
+ "order_status_returned": "Devolvida",
+ "order_status_delivered": "Entregue",
+ "order_status_cancelled": "Cancelada",
+ "reference": "Código de reserva",
+ "order_number": "Número da encomenda",
+ "tracking_number": "Número de seguimento",
+ "copy_reference": "Copiar o código de reserva {value}",
+ "copy_order_number": "Copiar o número da encomenda {value}",
+ "copy_tracking_number": "Copiar o número de seguimento {value}",
+ "copied_reference": "Código de reserva copiado",
+ "copied_order_number": "Número da encomenda copiado",
+ "copied_tracking_number": "Número de seguimento copiado",
+ "copy_failed": "Não foi possível copiar para a área de transferência",
+ "passengers": "Passageiros",
+ "seats": "Lugares",
+ "tickets": "Bilhetes",
+ "link_check_in": "Fazer check-in",
+ "link_manage": "Gerir reserva",
+ "link_ticket": "Bilhete",
+ "link_track": "Seguir",
+ "link_view_order": "Ver encomenda",
+ "check_in_label": "Check-in",
+ "check_out_label": "Check-out",
+ "from_time": "a partir das {time}",
+ "until_time": "até às {time}",
+ "nights": "{count, plural, one {# noite} other {# noites}}",
+ "pickup": "Levantamento",
+ "dropoff": "Devolução",
+ "party_size": "{count, plural, one {Mesa para # pessoa} other {Mesa para # pessoas}}",
+ "items_more": "e mais {count}",
+ "items_count": "{count, plural, one {# artigo} other {# artigos}}",
+ "total": "Total {total}",
+ "expected_by": "Chega até {date}",
+ "local_time": "hora local",
+ "local_time_title": "Hora local do lugar, não do seu fuso horário",
+ "route": "{from} para {to}"
+ },
"mv_position": "{index} de {total}",
"plugin_panel_show": "Mostrar o painel do plugin",
"plugin_panel_hide": "Ocultar o painel do plugin",
diff --git a/locales/ro/common.json b/locales/ro/common.json
index e037c4e25..ab19c8d1c 100644
--- a/locales/ro/common.json
+++ b/locales/ro/common.json
@@ -775,6 +775,69 @@
"copied": "Cod copiat",
"copy_failed": "Codul nu a putut fi copiat"
},
+ "structured_mail": {
+ "kind_flight": "Zbor",
+ "kind_train": "Tren",
+ "kind_bus": "Autobuz",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Mașină închiriată",
+ "kind_event": "Eveniment",
+ "kind_restaurant": "Restaurant",
+ "kind_order": "Comandă",
+ "kind_parcel": "Colet",
+ "region_flight": "Rezervare zbor",
+ "region_train": "Rezervare tren",
+ "region_bus": "Rezervare autobuz",
+ "region_lodging": "Rezervare hotel",
+ "region_rentalcar": "Rezervare mașină închiriată",
+ "region_event": "Rezervare eveniment",
+ "region_restaurant": "Rezervare la restaurant",
+ "region_shipment": "Comandă și livrare",
+ "status_cancelled": "Anulată",
+ "status_pending": "În așteptare",
+ "status_hold": "Rezervată provizoriu",
+ "order_status_payment_due": "Plată restantă",
+ "order_status_processing": "În procesare",
+ "order_status_problem": "Problemă",
+ "order_status_in_transit": "Expediată",
+ "order_status_pickup_available": "Gata de ridicare",
+ "order_status_returned": "Returnată",
+ "order_status_delivered": "Livrată",
+ "order_status_cancelled": "Anulată",
+ "reference": "Cod de rezervare",
+ "order_number": "Număr comandă",
+ "tracking_number": "Număr de urmărire",
+ "copy_reference": "Copiază codul de rezervare {value}",
+ "copy_order_number": "Copiază numărul comenzii {value}",
+ "copy_tracking_number": "Copiază numărul de urmărire {value}",
+ "copied_reference": "Codul de rezervare a fost copiat",
+ "copied_order_number": "Numărul comenzii a fost copiat",
+ "copied_tracking_number": "Numărul de urmărire a fost copiat",
+ "copy_failed": "Nu s-a putut copia în clipboard",
+ "passengers": "Pasageri",
+ "seats": "Locuri",
+ "tickets": "Bilete",
+ "link_check_in": "Check-in",
+ "link_manage": "Gestionează rezervarea",
+ "link_ticket": "Bilet",
+ "link_track": "Urmărește",
+ "link_view_order": "Vezi comanda",
+ "check_in_label": "Check-in",
+ "check_out_label": "Check-out",
+ "from_time": "de la {time}",
+ "until_time": "până la {time}",
+ "nights": "{count, plural, one {# noapte} few {# nopți} other {# de nopți}}",
+ "pickup": "Preluare",
+ "dropoff": "Predare",
+ "party_size": "{count, plural, one {Masă pentru # persoană} few {Masă pentru # persoane} other {Masă pentru # de persoane}}",
+ "items_more": "și încă {count}",
+ "items_count": "{count, plural, one {# articol} few {# articole} other {# de articole}}",
+ "total": "Total {total}",
+ "expected_by": "Sosește până pe {date}",
+ "local_time": "ora locală",
+ "local_time_title": "Ora locală a locului, nu cea din fusul tău orar",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} din {total}",
"plugin_panel_show": "Afișează panoul pluginului",
"plugin_panel_hide": "Ascunde panoul pluginului",
diff --git a/locales/ru/common.json b/locales/ru/common.json
index 358e3a6f6..0f8c7d9ef 100644
--- a/locales/ru/common.json
+++ b/locales/ru/common.json
@@ -775,6 +775,69 @@
"copied": "Код скопирован",
"copy_failed": "Не удалось скопировать код"
},
+ "structured_mail": {
+ "kind_flight": "Авиарейс",
+ "kind_train": "Поезд",
+ "kind_bus": "Автобус",
+ "kind_lodging": "Отель",
+ "kind_rentalcar": "Аренда авто",
+ "kind_event": "Мероприятие",
+ "kind_restaurant": "Ресторан",
+ "kind_order": "Заказ",
+ "kind_parcel": "Посылка",
+ "region_flight": "Бронирование авиабилета",
+ "region_train": "Бронирование поезда",
+ "region_bus": "Бронирование автобуса",
+ "region_lodging": "Бронирование отеля",
+ "region_rentalcar": "Бронирование автомобиля",
+ "region_event": "Бронирование мероприятия",
+ "region_restaurant": "Бронирование столика",
+ "region_shipment": "Заказ и доставка",
+ "status_cancelled": "Отменено",
+ "status_pending": "Ожидает подтверждения",
+ "status_hold": "Удерживается",
+ "order_status_payment_due": "Ожидает оплаты",
+ "order_status_processing": "Обрабатывается",
+ "order_status_problem": "Проблема",
+ "order_status_in_transit": "Отправлен",
+ "order_status_pickup_available": "Готов к выдаче",
+ "order_status_returned": "Возвращён",
+ "order_status_delivered": "Доставлен",
+ "order_status_cancelled": "Отменён",
+ "reference": "Номер бронирования",
+ "order_number": "Номер заказа",
+ "tracking_number": "Трек-номер",
+ "copy_reference": "Скопировать номер бронирования {value}",
+ "copy_order_number": "Скопировать номер заказа {value}",
+ "copy_tracking_number": "Скопировать трек-номер {value}",
+ "copied_reference": "Номер бронирования скопирован",
+ "copied_order_number": "Номер заказа скопирован",
+ "copied_tracking_number": "Трек-номер скопирован",
+ "copy_failed": "Не удалось скопировать в буфер обмена",
+ "passengers": "Пассажиры",
+ "seats": "Места",
+ "tickets": "Билеты",
+ "link_check_in": "Регистрация",
+ "link_manage": "Управление бронированием",
+ "link_ticket": "Билет",
+ "link_track": "Отследить",
+ "link_view_order": "Открыть заказ",
+ "check_in_label": "Заезд",
+ "check_out_label": "Выезд",
+ "from_time": "с {time}",
+ "until_time": "до {time}",
+ "nights": "{count, plural, one {# ночь} few {# ночи} many {# ночей} other {# ночи}}",
+ "pickup": "Получение",
+ "dropoff": "Возврат",
+ "party_size": "{count, plural, one {Столик на # человека} few {Столик на # человека} many {Столик на # человек} other {Столик на # человека}}",
+ "items_more": "и ещё {count}",
+ "items_count": "{count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}",
+ "total": "Итого {total}",
+ "expected_by": "Доставка до {date}",
+ "local_time": "местное время",
+ "local_time_title": "Местное время в этом месте, а не в вашем часовом поясе",
+ "route": "{from} — {to}"
+ },
"mv_position": "{index} из {total}",
"plugin_panel_show": "Показать панель плагина",
"plugin_panel_hide": "Скрыть панель плагина",
diff --git a/locales/sk/common.json b/locales/sk/common.json
index f8b7d5eb5..040b3e152 100644
--- a/locales/sk/common.json
+++ b/locales/sk/common.json
@@ -775,6 +775,69 @@
"copied": "Kód skopírovaný",
"copy_failed": "Kód sa nepodarilo skopírovať"
},
+ "structured_mail": {
+ "kind_flight": "Let",
+ "kind_train": "Vlak",
+ "kind_bus": "Autobus",
+ "kind_lodging": "Hotel",
+ "kind_rentalcar": "Požičané auto",
+ "kind_event": "Podujatie",
+ "kind_restaurant": "Reštaurácia",
+ "kind_order": "Objednávka",
+ "kind_parcel": "Zásielka",
+ "region_flight": "Rezervácia letu",
+ "region_train": "Rezervácia vlaku",
+ "region_bus": "Rezervácia autobusu",
+ "region_lodging": "Rezervácia hotela",
+ "region_rentalcar": "Rezervácia požičaného auta",
+ "region_event": "Rezervácia podujatia",
+ "region_restaurant": "Rezervácia stola",
+ "region_shipment": "Objednávka a doručenie",
+ "status_cancelled": "Zrušené",
+ "status_pending": "Čaká na potvrdenie",
+ "status_hold": "Blokované",
+ "order_status_payment_due": "Čaká na platbu",
+ "order_status_processing": "Spracúva sa",
+ "order_status_problem": "Problém",
+ "order_status_in_transit": "Odoslané",
+ "order_status_pickup_available": "Pripravené na vyzdvihnutie",
+ "order_status_returned": "Vrátené",
+ "order_status_delivered": "Doručené",
+ "order_status_cancelled": "Zrušené",
+ "reference": "Číslo rezervácie",
+ "order_number": "Číslo objednávky",
+ "tracking_number": "Číslo zásielky",
+ "copy_reference": "Kopírovať číslo rezervácie {value}",
+ "copy_order_number": "Kopírovať číslo objednávky {value}",
+ "copy_tracking_number": "Kopírovať číslo zásielky {value}",
+ "copied_reference": "Číslo rezervácie skopírované",
+ "copied_order_number": "Číslo objednávky skopírované",
+ "copied_tracking_number": "Číslo zásielky skopírované",
+ "copy_failed": "Kopírovanie do schránky zlyhalo",
+ "passengers": "Cestujúci",
+ "seats": "Miesta",
+ "tickets": "Vstupenky",
+ "link_check_in": "Odbaviť sa",
+ "link_manage": "Spravovať rezerváciu",
+ "link_ticket": "Vstupenka",
+ "link_track": "Sledovať",
+ "link_view_order": "Zobraziť objednávku",
+ "check_in_label": "Príchod",
+ "check_out_label": "Odchod",
+ "from_time": "od {time}",
+ "until_time": "do {time}",
+ "nights": "{count, plural, one {# noc} few {# noci} many {# noci} other {# nocí}}",
+ "pickup": "Vyzdvihnutie",
+ "dropoff": "Vrátenie",
+ "party_size": "{count, plural, one {Stôl pre # osobu} few {Stôl pre # osoby} many {Stôl pre # osoby} other {Stôl pre # osôb}}",
+ "items_more": "a {count} ďalšie",
+ "items_count": "{count, plural, one {# položka} few {# položky} many {# položky} other {# položiek}}",
+ "total": "Spolu {total}",
+ "expected_by": "Doručenie do {date}",
+ "local_time": "miestny čas",
+ "local_time_title": "Miestny čas na danom mieste, nie vo vašom časovom pásme",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} z {total}",
"plugin_panel_show": "Zobraziť panel doplnku",
"plugin_panel_hide": "Skryť panel doplnku",
diff --git a/locales/th/common.json b/locales/th/common.json
index 59ecfb5c1..0482f0086 100644
--- a/locales/th/common.json
+++ b/locales/th/common.json
@@ -1710,6 +1710,69 @@
"copied": "คัดลอกรหัสแล้ว!",
"copy_failed": "คัดลอกไม่สำเร็จ"
},
+ "structured_mail": {
+ "kind_flight": "เที่ยวบิน",
+ "kind_train": "รถไฟ",
+ "kind_bus": "รถบัส",
+ "kind_lodging": "โรงแรม",
+ "kind_rentalcar": "รถเช่า",
+ "kind_event": "กิจกรรม",
+ "kind_restaurant": "ร้านอาหาร",
+ "kind_order": "คำสั่งซื้อ",
+ "kind_parcel": "พัสดุ",
+ "region_flight": "การจองเที่ยวบิน",
+ "region_train": "การจองรถไฟ",
+ "region_bus": "การจองรถบัส",
+ "region_lodging": "การจองโรงแรม",
+ "region_rentalcar": "การจองรถเช่า",
+ "region_event": "การจองกิจกรรม",
+ "region_restaurant": "การจองโต๊ะอาหาร",
+ "region_shipment": "คำสั่งซื้อและการจัดส่ง",
+ "status_cancelled": "ยกเลิกแล้ว",
+ "status_pending": "รอการยืนยัน",
+ "status_hold": "กันที่ไว้",
+ "order_status_payment_due": "รอชำระเงิน",
+ "order_status_processing": "กำลังดำเนินการ",
+ "order_status_problem": "มีปัญหา",
+ "order_status_in_transit": "จัดส่งแล้ว",
+ "order_status_pickup_available": "พร้อมให้รับ",
+ "order_status_returned": "ส่งคืนแล้ว",
+ "order_status_delivered": "ส่งถึงแล้ว",
+ "order_status_cancelled": "ยกเลิกแล้ว",
+ "reference": "รหัสการจอง",
+ "order_number": "หมายเลขคำสั่งซื้อ",
+ "tracking_number": "หมายเลขพัสดุ",
+ "copy_reference": "คัดลอกรหัสการจอง {value}",
+ "copy_order_number": "คัดลอกหมายเลขคำสั่งซื้อ {value}",
+ "copy_tracking_number": "คัดลอกหมายเลขพัสดุ {value}",
+ "copied_reference": "คัดลอกรหัสการจองแล้ว",
+ "copied_order_number": "คัดลอกหมายเลขคำสั่งซื้อแล้ว",
+ "copied_tracking_number": "คัดลอกหมายเลขพัสดุแล้ว",
+ "copy_failed": "คัดลอกไปยังคลิปบอร์ดไม่ได้",
+ "passengers": "ผู้โดยสาร",
+ "seats": "ที่นั่ง",
+ "tickets": "ตั๋ว",
+ "link_check_in": "เช็คอิน",
+ "link_manage": "จัดการการจอง",
+ "link_ticket": "ตั๋ว",
+ "link_track": "ติดตามพัสดุ",
+ "link_view_order": "ดูคำสั่งซื้อ",
+ "check_in_label": "เช็คอิน",
+ "check_out_label": "เช็คเอาท์",
+ "from_time": "ตั้งแต่ {time}",
+ "until_time": "ภายใน {time}",
+ "nights": "{count, plural, other {# คืน}}",
+ "pickup": "รับรถ",
+ "dropoff": "คืนรถ",
+ "party_size": "{count, plural, other {โต๊ะสำหรับ # คน}}",
+ "items_more": "และอีก {count} รายการ",
+ "items_count": "{count, plural, other {# รายการ}}",
+ "total": "รวม {total}",
+ "expected_by": "ถึงภายใน {date}",
+ "local_time": "เวลาท้องถิ่น",
+ "local_time_title": "เวลาท้องถิ่นของสถานที่ ไม่ใช่เขตเวลาของคุณ",
+ "route": "{from} ไป {to}"
+ },
"mv_position": "{index} จาก {total}",
"copy": "คัดลอก",
"contact_added": "เพิ่มผู้ติดต่อแล้ว",
diff --git a/locales/tr/common.json b/locales/tr/common.json
index cdf7a8505..8e2a42bc5 100644
--- a/locales/tr/common.json
+++ b/locales/tr/common.json
@@ -775,6 +775,69 @@
"copied": "Kod kopyalandı",
"copy_failed": "Kod kopyalanamadı"
},
+ "structured_mail": {
+ "kind_flight": "Uçuş",
+ "kind_train": "Tren",
+ "kind_bus": "Otobüs",
+ "kind_lodging": "Otel",
+ "kind_rentalcar": "Kiralık araç",
+ "kind_event": "Etkinlik",
+ "kind_restaurant": "Restoran",
+ "kind_order": "Sipariş",
+ "kind_parcel": "Kargo",
+ "region_flight": "Uçuş rezervasyonu",
+ "region_train": "Tren rezervasyonu",
+ "region_bus": "Otobüs rezervasyonu",
+ "region_lodging": "Otel rezervasyonu",
+ "region_rentalcar": "Araç kiralama rezervasyonu",
+ "region_event": "Etkinlik rezervasyonu",
+ "region_restaurant": "Restoran rezervasyonu",
+ "region_shipment": "Sipariş ve teslimat",
+ "status_cancelled": "İptal edildi",
+ "status_pending": "Beklemede",
+ "status_hold": "Opsiyonlu",
+ "order_status_payment_due": "Ödeme bekleniyor",
+ "order_status_processing": "Hazırlanıyor",
+ "order_status_problem": "Sorun var",
+ "order_status_in_transit": "Kargoya verildi",
+ "order_status_pickup_available": "Teslim almaya hazır",
+ "order_status_returned": "İade edildi",
+ "order_status_delivered": "Teslim edildi",
+ "order_status_cancelled": "İptal edildi",
+ "reference": "Rezervasyon kodu",
+ "order_number": "Sipariş numarası",
+ "tracking_number": "Takip numarası",
+ "copy_reference": "{value} rezervasyon kodunu kopyala",
+ "copy_order_number": "{value} sipariş numarasını kopyala",
+ "copy_tracking_number": "{value} takip numarasını kopyala",
+ "copied_reference": "Rezervasyon kodu kopyalandı",
+ "copied_order_number": "Sipariş numarası kopyalandı",
+ "copied_tracking_number": "Takip numarası kopyalandı",
+ "copy_failed": "Panoya kopyalanamadı",
+ "passengers": "Yolcular",
+ "seats": "Koltuklar",
+ "tickets": "Biletler",
+ "link_check_in": "Check-in yap",
+ "link_manage": "Rezervasyonu yönet",
+ "link_ticket": "Bilet",
+ "link_track": "Takip et",
+ "link_view_order": "Siparişi görüntüle",
+ "check_in_label": "Giriş",
+ "check_out_label": "Çıkış",
+ "from_time": "{time} itibarıyla",
+ "until_time": "en geç {time}",
+ "nights": "{count, plural, one {# gece} other {# gece}}",
+ "pickup": "Teslim alma",
+ "dropoff": "Teslim etme",
+ "party_size": "{count, plural, one {# kişilik masa} other {# kişilik masa}}",
+ "items_more": "ve {count} tane daha",
+ "items_count": "{count, plural, one {# ürün} other {# ürün}}",
+ "total": "Toplam {total}",
+ "expected_by": "En geç {date} tarihinde gelir",
+ "local_time": "yerel saat",
+ "local_time_title": "Yerin yerel saati, sizin saat diliminiz değil",
+ "route": "{from} – {to}"
+ },
"mv_position": "{index} / {total}",
"plugin_panel_show": "Eklenti panelini göster",
"plugin_panel_hide": "Eklenti panelini gizle",
diff --git a/locales/uk/common.json b/locales/uk/common.json
index e645074a5..0f76178d0 100644
--- a/locales/uk/common.json
+++ b/locales/uk/common.json
@@ -775,6 +775,69 @@
"copied": "Код скопійовано",
"copy_failed": "Не вдалося скопіювати код"
},
+ "structured_mail": {
+ "kind_flight": "Авіарейс",
+ "kind_train": "Потяг",
+ "kind_bus": "Автобус",
+ "kind_lodging": "Готель",
+ "kind_rentalcar": "Оренда авто",
+ "kind_event": "Подія",
+ "kind_restaurant": "Ресторан",
+ "kind_order": "Замовлення",
+ "kind_parcel": "Посилка",
+ "region_flight": "Бронювання авіаквитка",
+ "region_train": "Бронювання потяга",
+ "region_bus": "Бронювання автобуса",
+ "region_lodging": "Бронювання готелю",
+ "region_rentalcar": "Бронювання авто",
+ "region_event": "Бронювання події",
+ "region_restaurant": "Бронювання столика",
+ "region_shipment": "Замовлення і доставка",
+ "status_cancelled": "Скасовано",
+ "status_pending": "Очікує підтвердження",
+ "status_hold": "Утримується",
+ "order_status_payment_due": "Очікує оплати",
+ "order_status_processing": "Обробляється",
+ "order_status_problem": "Проблема",
+ "order_status_in_transit": "Відправлено",
+ "order_status_pickup_available": "Готове до видачі",
+ "order_status_returned": "Повернено",
+ "order_status_delivered": "Доставлено",
+ "order_status_cancelled": "Скасовано",
+ "reference": "Номер бронювання",
+ "order_number": "Номер замовлення",
+ "tracking_number": "Трек-номер",
+ "copy_reference": "Скопіювати номер бронювання {value}",
+ "copy_order_number": "Скопіювати номер замовлення {value}",
+ "copy_tracking_number": "Скопіювати трек-номер {value}",
+ "copied_reference": "Номер бронювання скопійовано",
+ "copied_order_number": "Номер замовлення скопійовано",
+ "copied_tracking_number": "Трек-номер скопійовано",
+ "copy_failed": "Не вдалося скопіювати в буфер обміну",
+ "passengers": "Пасажири",
+ "seats": "Місця",
+ "tickets": "Квитки",
+ "link_check_in": "Реєстрація",
+ "link_manage": "Керувати бронюванням",
+ "link_ticket": "Квиток",
+ "link_track": "Відстежити",
+ "link_view_order": "Переглянути замовлення",
+ "check_in_label": "Заїзд",
+ "check_out_label": "Виїзд",
+ "from_time": "з {time}",
+ "until_time": "до {time}",
+ "nights": "{count, plural, one {# ніч} few {# ночі} many {# ночей} other {# ночі}}",
+ "pickup": "Отримання",
+ "dropoff": "Повернення",
+ "party_size": "{count, plural, one {Столик на # особу} few {Столик на # особи} many {Столик на # осіб} other {Столик на # особи}}",
+ "items_more": "і ще {count}",
+ "items_count": "{count, plural, one {# товар} few {# товари} many {# товарів} other {# товару}}",
+ "total": "Разом {total}",
+ "expected_by": "Доставка до {date}",
+ "local_time": "місцевий час",
+ "local_time_title": "Місцевий час у цьому місці, а не у вашому часовому поясі",
+ "route": "{from} — {to}"
+ },
"mv_position": "{index} з {total}",
"plugin_panel_show": "Показати панель плагіна",
"plugin_panel_hide": "Сховати панель плагіна",
diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json
index 4d628a87d..aba8e8a9c 100644
--- a/locales/zh-TW/common.json
+++ b/locales/zh-TW/common.json
@@ -775,6 +775,69 @@
"copied": "驗證碼已複製",
"copy_failed": "無法複製驗證碼"
},
+ "structured_mail": {
+ "kind_flight": "航班",
+ "kind_train": "火車",
+ "kind_bus": "巴士",
+ "kind_lodging": "飯店",
+ "kind_rentalcar": "租車",
+ "kind_event": "活動",
+ "kind_restaurant": "餐廳",
+ "kind_order": "訂單",
+ "kind_parcel": "包裹",
+ "region_flight": "航班訂位",
+ "region_train": "火車訂票",
+ "region_bus": "巴士訂票",
+ "region_lodging": "飯店訂房",
+ "region_rentalcar": "租車預約",
+ "region_event": "活動預約",
+ "region_restaurant": "餐廳訂位",
+ "region_shipment": "訂單與配送",
+ "status_cancelled": "已取消",
+ "status_pending": "待確認",
+ "status_hold": "已保留",
+ "order_status_payment_due": "待付款",
+ "order_status_processing": "處理中",
+ "order_status_problem": "有問題",
+ "order_status_in_transit": "已出貨",
+ "order_status_pickup_available": "可取貨",
+ "order_status_returned": "已退回",
+ "order_status_delivered": "已送達",
+ "order_status_cancelled": "已取消",
+ "reference": "訂位代號",
+ "order_number": "訂單編號",
+ "tracking_number": "貨件追蹤號碼",
+ "copy_reference": "複製訂位代號 {value}",
+ "copy_order_number": "複製訂單編號 {value}",
+ "copy_tracking_number": "複製貨件追蹤號碼 {value}",
+ "copied_reference": "已複製訂位代號",
+ "copied_order_number": "已複製訂單編號",
+ "copied_tracking_number": "已複製貨件追蹤號碼",
+ "copy_failed": "無法複製到剪貼簿",
+ "passengers": "乘客",
+ "seats": "座位",
+ "tickets": "票券",
+ "link_check_in": "報到",
+ "link_manage": "管理訂位",
+ "link_ticket": "票券",
+ "link_track": "追蹤貨件",
+ "link_view_order": "查看訂單",
+ "check_in_label": "入住",
+ "check_out_label": "退房",
+ "from_time": "{time} 起",
+ "until_time": "{time} 前",
+ "nights": "{count, plural, other {# 晚}}",
+ "pickup": "取車",
+ "dropoff": "還車",
+ "party_size": "{count, plural, other {# 人桌}}",
+ "items_more": "及其他 {count} 件",
+ "items_count": "{count, plural, other {# 件商品}}",
+ "total": "總計 {total}",
+ "expected_by": "預計 {date} 前送達",
+ "local_time": "當地時間",
+ "local_time_title": "這是該地點的當地時間,而非你所在時區的時間",
+ "route": "{from} 至 {to}"
+ },
"mv_position": "第 {index} 封,共 {total} 封",
"plugin_panel_show": "顯示外掛程式面板",
"plugin_panel_hide": "隱藏外掛程式面板",
diff --git a/locales/zh/common.json b/locales/zh/common.json
index 80744b109..1edf0891f 100644
--- a/locales/zh/common.json
+++ b/locales/zh/common.json
@@ -775,6 +775,69 @@
"copied": "验证码已复制",
"copy_failed": "无法复制验证码"
},
+ "structured_mail": {
+ "kind_flight": "航班",
+ "kind_train": "火车",
+ "kind_bus": "巴士",
+ "kind_lodging": "酒店",
+ "kind_rentalcar": "租车",
+ "kind_event": "活动",
+ "kind_restaurant": "餐厅",
+ "kind_order": "订单",
+ "kind_parcel": "包裹",
+ "region_flight": "航班预订",
+ "region_train": "火车预订",
+ "region_bus": "巴士预订",
+ "region_lodging": "酒店预订",
+ "region_rentalcar": "租车预订",
+ "region_event": "活动预订",
+ "region_restaurant": "餐厅预订",
+ "region_shipment": "订单和配送",
+ "status_cancelled": "已取消",
+ "status_pending": "待确认",
+ "status_hold": "已预留",
+ "order_status_payment_due": "待付款",
+ "order_status_processing": "处理中",
+ "order_status_problem": "有问题",
+ "order_status_in_transit": "已发货",
+ "order_status_pickup_available": "待取件",
+ "order_status_returned": "已退回",
+ "order_status_delivered": "已送达",
+ "order_status_cancelled": "已取消",
+ "reference": "预订编号",
+ "order_number": "订单号",
+ "tracking_number": "运单号",
+ "copy_reference": "复制预订编号 {value}",
+ "copy_order_number": "复制订单号 {value}",
+ "copy_tracking_number": "复制运单号 {value}",
+ "copied_reference": "已复制预订编号",
+ "copied_order_number": "已复制订单号",
+ "copied_tracking_number": "已复制运单号",
+ "copy_failed": "无法复制到剪贴板",
+ "passengers": "乘客",
+ "seats": "座位",
+ "tickets": "门票",
+ "link_check_in": "值机",
+ "link_manage": "管理预订",
+ "link_ticket": "门票",
+ "link_track": "查询物流",
+ "link_view_order": "查看订单",
+ "check_in_label": "入住",
+ "check_out_label": "退房",
+ "from_time": "{time} 起",
+ "until_time": "{time} 前",
+ "nights": "{count, plural, other {# 晚}}",
+ "pickup": "取车",
+ "dropoff": "还车",
+ "party_size": "{count, plural, other {# 人桌}}",
+ "items_more": "等另外 {count} 件",
+ "items_count": "{count, plural, other {# 件商品}}",
+ "total": "合计 {total}",
+ "expected_by": "预计 {date} 前送达",
+ "local_time": "当地时间",
+ "local_time_title": "这是该地点的当地时间,而不是你所在时区的时间",
+ "route": "{from} 至 {to}"
+ },
"mv_position": "第 {index} 封,共 {total} 封",
"plugin_panel_show": "显示插件面板",
"plugin_panel_hide": "隐藏插件面板",