@qite/tide-booking-component 1.4.34 → 1.4.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/build/build-cjs/index.js +1627 -374
  2. package/build/build-cjs/qsm/types.d.ts +0 -1
  3. package/build/build-cjs/search-results/components/filters/filters.d.ts +2 -2
  4. package/build/build-cjs/search-results/components/flight/flight-results.d.ts +2 -0
  5. package/build/build-cjs/search-results/components/hotel/hotel-card.d.ts +1 -0
  6. package/build/build-cjs/search-results/components/itinerary/index.d.ts +2 -2
  7. package/build/build-cjs/search-results/store/search-results-slice.d.ts +11 -2
  8. package/build/build-cjs/search-results/types.d.ts +0 -14
  9. package/build/build-esm/index.js +1627 -374
  10. package/build/build-esm/qsm/types.d.ts +0 -1
  11. package/build/build-esm/search-results/components/filters/filters.d.ts +2 -2
  12. package/build/build-esm/search-results/components/flight/flight-results.d.ts +2 -0
  13. package/build/build-esm/search-results/components/hotel/hotel-card.d.ts +1 -0
  14. package/build/build-esm/search-results/components/itinerary/index.d.ts +2 -2
  15. package/build/build-esm/search-results/store/search-results-slice.d.ts +11 -2
  16. package/build/build-esm/search-results/types.d.ts +0 -14
  17. package/package.json +2 -2
  18. package/src/booking-wizard/features/booking/booking-self-contained.tsx +0 -1
  19. package/src/booking-wizard/features/travelers-form/controls/gender-control.tsx +5 -5
  20. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +10 -10
  21. package/src/content/components/icon.tsx +1 -1
  22. package/src/content/features/content-page/content-page-self-contained.tsx +0 -1
  23. package/src/qsm/components/QSMContainer/qsm-container.tsx +15 -13
  24. package/src/qsm/components/mobile-filter-modal/index.tsx +12 -10
  25. package/src/qsm/components/travel-class-picker/index.tsx +5 -3
  26. package/src/qsm/components/travel-input/index.tsx +15 -12
  27. package/src/qsm/components/travel-input-group/index.tsx +14 -3
  28. package/src/qsm/components/travel-nationality-picker/index.tsx +5 -3
  29. package/src/qsm/components/travel-type-picker/index.tsx +5 -3
  30. package/src/qsm/qsm-configuration-context.ts +0 -1
  31. package/src/qsm/types.ts +0 -1
  32. package/src/search-results/components/filters/filters.tsx +15 -16
  33. package/src/search-results/components/flight/flight-results.tsx +168 -1099
  34. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +21 -24
  35. package/src/search-results/components/hotel/hotel-card.tsx +4 -3
  36. package/src/search-results/components/icon.tsx +1 -1
  37. package/src/search-results/components/itinerary/index.tsx +229 -129
  38. package/src/search-results/components/round-trip/round-trip-results.tsx +1 -1
  39. package/src/search-results/components/search-results-container/search-results-container.tsx +45 -33
  40. package/src/search-results/components/spinner/spinner.tsx +3 -1
  41. package/src/search-results/components/tab-views/index.tsx +13 -7
  42. package/src/search-results/features/flights/flight-search-results-self-contained.tsx +1 -14
  43. package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +1 -14
  44. package/src/search-results/store/search-results-slice.ts +37 -3
  45. package/src/search-results/types.ts +0 -15
  46. package/src/shared/translations/ar-SA.json +70 -0
  47. package/src/shared/translations/da-DK.json +70 -0
  48. package/src/shared/translations/de-DE.json +70 -0
  49. package/src/shared/translations/en-GB.json +71 -1
  50. package/src/shared/translations/es-ES.json +70 -0
  51. package/src/shared/translations/fr-BE.json +71 -1
  52. package/src/shared/translations/fr-FR.json +70 -0
  53. package/src/shared/translations/is-IS.json +72 -2
  54. package/src/shared/translations/it-IT.json +70 -0
  55. package/src/shared/translations/ja-JP.json +72 -2
  56. package/src/shared/translations/nl-BE.json +70 -0
  57. package/src/shared/translations/nl-NL.json +70 -0
  58. package/src/shared/translations/no-NO.json +72 -2
  59. package/src/shared/translations/pl-PL.json +70 -0
  60. package/src/shared/translations/pt-PT.json +70 -0
  61. package/src/shared/translations/sv-SE.json +72 -2
  62. package/styles/components/_search.scss +7 -1
@@ -3,13 +3,13 @@ import { useDispatch, useSelector } from 'react-redux';
3
3
  import { SearchResultsRootState } from '../../store/search-results-store';
4
4
  import SearchResultsConfigurationContext from '../../search-results-configuration-context';
5
5
 
6
- import { resetFilters, setSortKey, setResults, setIsLoading, setSelectedHotel } from '../../store/search-results-slice';
6
+ import { resetFilters, setSortKey, setResults, setIsLoading, setSelectedHotel, setBookingPackageDetails, setEntry } from '../../store/search-results-slice';
7
7
  import { Filter, SortingOption } from '../../types';
8
8
  import useMediaQuery from '../../../shared/utils/use-media-query-util';
9
9
  import Filters from '../filters/filters';
10
10
  import ItemPicker from '../item-picker';
11
11
 
12
- import { TideClientConfig, details, search } from '@qite/tide-client';
12
+ import { TideClientConfig, detailsWL, search } from '@qite/tide-client';
13
13
  import {
14
14
  BookingPackageDestination,
15
15
  BookingPackageDetailsRequest,
@@ -27,17 +27,21 @@ import TabViews from '../tab-views';
27
27
  import HotelAccommodationResults from '../hotel/hotel-accommodation-results';
28
28
  import RoundTripResults from '../round-trip/round-trip-results';
29
29
  import { enrichFiltersWithResults } from '../filters/utility';
30
+ import FlightResults from '../flight/flight-results';
31
+ import { getTranslations } from '../../../shared/utils/localization-util';
30
32
 
31
33
  const SearchResultsContainer: React.FC = () => {
32
34
  const isMobile = useMediaQuery('(max-width: 1200px)');
33
35
  const dispatch = useDispatch();
34
36
  const context = useContext(SearchResultsConfigurationContext);
35
- const { results, isLoading, filters, sortKey, selectedHotelId } = useSelector((state: SearchResultsRootState) => state.searchResults);
37
+ const translations = getTranslations(context?.languageCode ?? 'en-GB');
38
+ const { results, bookingPackageDetails, isLoading, filters, sortKey, selectedHotelId } = useSelector((state: SearchResultsRootState) => state.searchResults);
36
39
 
37
40
  const [searchTrigger, setSearchTrigger] = useState(0);
38
41
  const [initialFiltersSet, setInitialFiltersSet] = useState(false);
39
42
  const [initialFilters, setInitialFilters] = useState<Filter[]>([]);
40
43
 
44
+ // seperate Search
41
45
  useEffect(() => {
42
46
  const runSearch = async () => {
43
47
  dispatch(setIsLoading(true));
@@ -155,6 +159,7 @@ const SearchResultsContainer: React.FC = () => {
155
159
  runSearch();
156
160
  }, [location.search, searchTrigger]);
157
161
 
162
+ // Seperate detailsCall
158
163
  useEffect(() => {
159
164
  const fetchPackageDetails = async () => {
160
165
  if (!selectedHotelId || !context) return;
@@ -192,12 +197,10 @@ const SearchResultsContainer: React.FC = () => {
192
197
  }
193
198
  };
194
199
 
195
- const detailsResponse = await details(config, detailsRequest);
196
-
197
- console.log('Package details:', detailsResponse);
198
-
199
- // TODO: store flights / details in redux
200
- // dispatch(setSelectedHotelDetails(details));
200
+ const detailsWLResponse = await detailsWL(config, detailsRequest);
201
+ console.log('Details with entryLight:', detailsWLResponse);
202
+ dispatch(setBookingPackageDetails({ details: detailsWLResponse?.payload?.bookingPackage }));
203
+ dispatch(setEntry({ entry: detailsWLResponse?.payload?.entry }));
201
204
  } catch (err) {
202
205
  console.error('Failed to fetch package details', err);
203
206
  }
@@ -236,26 +239,23 @@ const SearchResultsContainer: React.FC = () => {
236
239
  return requestRooms;
237
240
  };
238
241
 
239
- const [isMobileFiltersOpen, setIsMobileFiltersOpen] = useState(false);
242
+ const [filtersOpen, setFiltersOpen] = useState(false);
243
+ const [itineraryOpen, setItineraryOpen] = useState(false);
240
244
 
241
245
  const handleSortChange = (newSortKey: string) => {
242
246
  dispatch(setSortKey(newSortKey));
243
247
  };
244
248
 
245
- const handleSetIsMobileFiltersOpen = () => {
246
- setIsMobileFiltersOpen(!isMobileFiltersOpen);
247
- };
248
-
249
249
  useEffect(() => {
250
250
  if (typeof document !== 'undefined') {
251
- document.body.classList.toggle('has-overlay', isMobileFiltersOpen);
251
+ document.body.classList.toggle('has-overlay', filtersOpen);
252
252
  }
253
- }, [isMobileFiltersOpen]);
253
+ }, [filtersOpen]);
254
254
 
255
255
  const sortingOptions: SortingOption[] = [
256
- { key: 'price-asc', label: 'Price: Low to High' },
257
- { key: 'price-desc', label: 'Price: High to Low' },
258
- { key: 'departure-date', label: 'Departure Date' }
256
+ { key: 'price-asc', label: translations.SRP.PRICE_ASC },
257
+ { key: 'price-desc', label: translations.SRP.PRICE_DESC },
258
+ { key: 'departure-date', label: translations.SRP.DEPARTURE_ASC }
259
259
  ];
260
260
 
261
261
  return (
@@ -266,29 +266,37 @@ const SearchResultsContainer: React.FC = () => {
266
266
  {context.showFilters && (
267
267
  <Filters
268
268
  filters={filters}
269
- isMobileFiltersOpen={isMobileFiltersOpen}
270
- handleSetIsMobileFiltersOpen={handleSetIsMobileFiltersOpen}
269
+ isOpen={filtersOpen}
270
+ handleSetIsOpen={() => setFiltersOpen(!filtersOpen)}
271
271
  handleApplyFilters={() => setSearchTrigger((prev) => prev + 1)}
272
272
  isLoading={isLoading}
273
273
  />
274
274
  )}
275
275
  {context.type === 'hotel-flight' && (
276
- <Itinerary isMobileFiltersOpen={isMobileFiltersOpen} handleSetIsMobileFiltersOpen={handleSetIsMobileFiltersOpen} isLoading={isLoading} />
276
+ <Itinerary isOpen={itineraryOpen} handleSetIsOpen={() => setItineraryOpen(!itineraryOpen)} isLoading={isLoading} />
277
277
  )}
278
278
  {/* ---------------- Results ---------------- */}
279
279
  <div className="search__results">
280
280
  {isMobile && (
281
281
  <div className="search__result-row">
282
- <div className="cta cta--filter" onClick={() => setIsMobileFiltersOpen(true)}>
283
- <Icon name="ui-filter" className="mobile-filters-button__icon" height={16} />
284
- {context.translations?.filters}
282
+ <div className="search__results__actions">
283
+ {context.showFilters && (
284
+ <div className="cta cta--filter" onClick={() => setFiltersOpen(true)}>
285
+ <Icon name="ui-filter" className="mobile-filters-button__icon" height={16} />
286
+ {translations.SRP.FILTERS}
287
+ </div>
288
+ )}
289
+ <div className="cta cta--filter" onClick={() => setItineraryOpen(true)}>
290
+ <Icon name="ui-calendar" className="mobile-filters-button__icon" height={16} />
291
+ {translations.SRP.SHOW_ITINERARY}
292
+ </div>
285
293
  </div>
286
294
  {sortingOptions && sortingOptions.length > 0 && (
287
295
  <ItemPicker
288
296
  items={sortingOptions}
289
297
  selection={sortKey || undefined}
290
- label="Sort by"
291
- placeholder="Sort by"
298
+ label={translations.SRP.SORTBY}
299
+ placeholder={translations.SRP.SORTBY}
292
300
  classModifier="travel-class-picker__items"
293
301
  onPick={handleSortChange}
294
302
  />
@@ -300,7 +308,7 @@ const SearchResultsContainer: React.FC = () => {
300
308
  <span className="search__result-row-text">
301
309
  {!isLoading && (
302
310
  <>
303
- {results?.length ?? 4} {context.translations?.totalResultsLabel}
311
+ {results?.length ?? 4} {translations.SRP.TOTAL_RESULTS_LABEL}
304
312
  </>
305
313
  )}
306
314
  </span>
@@ -309,8 +317,8 @@ const SearchResultsContainer: React.FC = () => {
309
317
  <ItemPicker
310
318
  items={sortingOptions}
311
319
  selection={sortKey || undefined}
312
- label="Sort by"
313
- placeholder="Sort by"
320
+ label={translations.SRP.SORTBY}
321
+ placeholder={translations.SRP.SORTBY}
314
322
  classModifier="travel-class-picker__items"
315
323
  onPick={handleSortChange}
316
324
  />
@@ -321,14 +329,18 @@ const SearchResultsContainer: React.FC = () => {
321
329
  <div className="search__results__wrapper">
322
330
  {context.showTabViews && <TabViews />}
323
331
 
324
- {context.showRoundTripResults && <RoundTripResults />}
332
+ {/* {context.showRoundTripResults && <RoundTripResults />} */}
325
333
 
326
- {/* {context.showFlightResults && <FlightResults isDeparture={true} />} */}
334
+ {context.showFlightResults && bookingPackageDetails?.outwardFlights && (
335
+ <FlightResults flights={bookingPackageDetails.outwardFlights} isDeparture={true} />
336
+ )}
327
337
 
328
338
  {context.showHotelAccommodationResults && <HotelAccommodationResults isLoading={isLoading} context={context} />}
329
339
  {/* {context.showFlightAccommodationResults && <FlightAccommodationResults />} */}
330
340
 
331
- {/* {context.showFlightResults && <FlightResults isDeparture={false} />} */}
341
+ {context.showFlightResults && bookingPackageDetails?.returnFlights && (
342
+ <FlightResults flights={bookingPackageDetails.returnFlights} isDeparture={false} />
343
+ )}
332
344
  </div>
333
345
  </div>
334
346
  </div>
@@ -1,12 +1,14 @@
1
1
  import React, { useContext } from 'react';
2
2
  import SearchResultsConfigurationContext from '../../search-results-configuration-context';
3
+ import { getTranslations } from '../../../shared/utils/localization-util';
3
4
 
4
5
  const Spinner: React.FC = () => {
5
6
  const context = useContext(SearchResultsConfigurationContext);
7
+ const translations = getTranslations(context?.languageCode ?? 'en-GB');
6
8
  return (
7
9
  <div className="spinner__container">
8
10
  <span className="spinner__icon" />
9
- <span className="spinner__label">{context?.translations?.loading}</span>
11
+ <span className="spinner__label">{translations?.SRP.LOADING}</span>
10
12
  </div>
11
13
  );
12
14
  };
@@ -1,13 +1,19 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import Icon from '../icon';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
4
  import { SearchResultsRootState } from '../../store/search-results-store';
5
5
  import { setActiveTab } from '../../store/search-results-slice';
6
+ import { getTranslations } from '../../../shared/utils/localization-util';
7
+ import SearchResultsConfigurationContext from '../../search-results-configuration-context';
6
8
 
7
9
  interface TabViewsProps {}
8
10
 
9
11
  const TabViews: React.FC<TabViewsProps> = () => {
12
+ const context = useContext(SearchResultsConfigurationContext);
13
+ const translations = getTranslations(context?.languageCode ?? 'en-GB');
14
+
10
15
  const dispatch = useDispatch();
16
+
11
17
  const { activeTab } = useSelector((state: SearchResultsRootState) => state.searchResults);
12
18
 
13
19
  const handleSortChange = (tab: string) => {
@@ -21,21 +27,21 @@ const TabViews: React.FC<TabViewsProps> = () => {
21
27
  className={`search__results__tab-view ${activeTab === 'extended' ? 'search__results__tab-view--active' : ''}`}
22
28
  onClick={() => handleSortChange('extended')}>
23
29
  <Icon name="ui-extended" height={16} />
24
- Extended
30
+ {translations.SRP.EXTENDED}
25
31
  </button>
26
32
  <button
27
33
  type="button"
28
34
  className={`search__results__tab-view ${activeTab === 'compact' ? 'search__results__tab-view--active' : ''}`}
29
35
  onClick={() => handleSortChange('compact')}>
30
36
  <Icon name="ui-compact" height={16} />
31
- Compact
37
+ {translations.SRP.COMPACT}
32
38
  </button>
33
39
  <button
34
40
  type="button"
35
- className={`search__results__tab-view ${activeTab === 'comparator' ? 'search__results__tab-view--active' : ''}`}
36
- onClick={() => handleSortChange('comparator')}>
37
- <Icon name="ui-comparator" height={16} />
38
- Comparator
41
+ className={`search__results__tab-view ${activeTab === 'list' ? 'search__results__tab-view--active' : ''}`}
42
+ onClick={() => handleSortChange('list')}>
43
+ <Icon name="ui-list" height={16} />
44
+ {translations.SRP.LIST}
39
45
  </button>
40
46
  </div>
41
47
  );
@@ -245,23 +245,10 @@ const FlightSearchResultsSelfContained: React.FC<FlightSearchResultsSelfContaine
245
245
  // Pagination
246
246
 
247
247
  // State & UI
248
- noResultsLabel: 'No products found.',
249
248
  isLoading: false,
250
249
  customSpinner: null,
251
250
 
252
- translations: {
253
- filters: 'Filters',
254
- filterTitle: 'Filter resultaten',
255
- resetButton: 'Reset',
256
- sortBy: 'Sorteren op',
257
- noResults: 'Geen resultaten gevonden.',
258
- totalResultsLabel: 'resultaten gevonden',
259
- luggageIncluded: 'Bagage inbegrepen',
260
- apply: 'Toepassen',
261
- loading: 'Laden...',
262
- cancel: 'Annuleren',
263
- searchResultCTA: 'Bekijk details'
264
- }
251
+ languageCode: 'en-GB'
265
252
  };
266
253
 
267
254
  return (
@@ -171,23 +171,10 @@ const HotelSearchResultsSelfContained: React.FC<HotelSearchResultsSelfContainedP
171
171
  // },
172
172
 
173
173
  // State & UI
174
- noResultsLabel: 'No products found.',
175
174
  isLoading: false,
176
175
  customSpinner: null,
177
176
 
178
- translations: {
179
- filters: 'Filters',
180
- filterTitle: 'Filter resultaten',
181
- resetButton: 'Reset',
182
- sortBy: 'Sorteren op',
183
- noResults: 'Geen resultaten gevonden.',
184
- totalResultsLabel: 'resultaten gevonden',
185
- luggageIncluded: 'Bagage inbegrepen',
186
- apply: 'Toepassen',
187
- loading: 'Laden...',
188
- cancel: 'Annuleren',
189
- searchResultCTA: 'Bekijk details'
190
- }
177
+ languageCode: 'en-GB'
191
178
  };
192
179
 
193
180
  return (
@@ -1,10 +1,12 @@
1
1
  import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
2
  import { Filter } from '../types';
3
- import { BookingPackageItem } from '@qite/tide-client/build/types';
3
+ import { BookingPackage, BookingPackageItem, EntryLight } from '@qite/tide-client/build/types';
4
4
 
5
5
  export interface SearchResultsState {
6
6
  results: BookingPackageItem[];
7
7
  selectedHotelId: number | null;
8
+ bookingPackageDetails: BookingPackage | null;
9
+ entry: EntryLight | null;
8
10
  isLoading: boolean;
9
11
  filters: Filter[];
10
12
  sortKey: string | null;
@@ -15,6 +17,8 @@ export interface SearchResultsState {
15
17
  const initialState: SearchResultsState = {
16
18
  results: [],
17
19
  selectedHotelId: null,
20
+ bookingPackageDetails: null,
21
+ entry: null,
18
22
  isLoading: false,
19
23
  filters: [],
20
24
  sortKey: null,
@@ -32,6 +36,24 @@ const searchResultsSlice = createSlice({
32
36
  setSelectedHotel(state, action: PayloadAction<number | null>) {
33
37
  state.selectedHotelId = action.payload;
34
38
  },
39
+ setBookingPackageDetails(state, action: PayloadAction<{ details: BookingPackage }>) {
40
+ state.bookingPackageDetails = action.payload.details;
41
+ },
42
+ setEntry(state, action: PayloadAction<{ entry: EntryLight }>) {
43
+ state.entry = action.payload.entry;
44
+ },
45
+ selectFlight(state, action: PayloadAction<{ flightOptionId: string; isDeparture: boolean }>) {
46
+ if (!state.bookingPackageDetails) return;
47
+
48
+ const { flightOptionId, isDeparture } = action.payload;
49
+
50
+ const flightKey = isDeparture ? 'outwardFlights' : 'returnFlights';
51
+
52
+ state.bookingPackageDetails[flightKey] = state.bookingPackageDetails[flightKey].map((flight) => ({
53
+ ...flight,
54
+ isSelected: flight.flightOptionId === flightOptionId
55
+ }));
56
+ },
35
57
  setIsLoading(state, action: PayloadAction<boolean>) {
36
58
  state.isLoading = action.payload;
37
59
  },
@@ -70,7 +92,19 @@ const searchResultsSlice = createSlice({
70
92
  }
71
93
  });
72
94
 
73
- export const { setResults, setSelectedHotel, setIsLoading, setFilters, resetFilters, setSortKey, setActiveTab, setCurrentPage, resetSearchState } =
74
- searchResultsSlice.actions;
95
+ export const {
96
+ setResults,
97
+ setSelectedHotel,
98
+ setBookingPackageDetails,
99
+ setEntry,
100
+ selectFlight,
101
+ setIsLoading,
102
+ setFilters,
103
+ resetFilters,
104
+ setSortKey,
105
+ setActiveTab,
106
+ setCurrentPage,
107
+ resetSearchState
108
+ } = searchResultsSlice.actions;
75
109
 
76
110
  export default searchResultsSlice.reducer;
@@ -37,24 +37,9 @@ export interface SearchResultsConfiguration {
37
37
  // pagination?: PaginationConfig;
38
38
 
39
39
  // State
40
- noResultsLabel?: string;
41
40
  isLoading?: boolean;
42
41
  customSpinner?: ReactNode;
43
42
 
44
- translations?: {
45
- filters?: string;
46
- filterTitle?: string;
47
- resetButton?: string;
48
- sortBy?: string;
49
- noResults?: string;
50
- totalResultsLabel?: string;
51
- luggageIncluded?: string;
52
- cancel?: string;
53
- apply?: string;
54
- loading?: string;
55
- searchResultCTA?: string;
56
- };
57
-
58
43
  cmsHotelData?: any[];
59
44
  languageCode?: string;
60
45
  }
@@ -134,8 +134,11 @@
134
134
  "CHILD": "طفل",
135
135
  "CHILDREN": "أطفال",
136
136
  "GENDER": "اللقب",
137
+ "GENDER_ID": "الجنس حسب جواز السفر/بطاقة الهوية",
137
138
  "MALE": "السيد",
139
+ "MALE_GENDER": "ذكر",
138
140
  "FEMALE": "السيدة",
141
+ "FEMALE_GENDER": "أنثى",
139
142
  "OTHER": "آخر",
140
143
  "MAIN_BOOKER": "الحاجز الرئيسي",
141
144
  "FIRST_NAME": "الاسم الأول",
@@ -245,5 +248,72 @@
245
248
  "LABEL_IDLE": "طباعة العرض",
246
249
  "LABEL_CREATING": "جارٍ إنشاء العرض…",
247
250
  "LABEL_PRINTING": "جارٍ إنشاء ملف PDF…"
251
+ },
252
+ "QSM": {
253
+ "MULTIDESTINATION": "وجهات متعددة",
254
+ "PACKAGES": "باقات",
255
+ "TRANSPORT_HOTEL": "النقل + الفندق",
256
+ "ACCOMMODATION": "الإقامة",
257
+ "TRANSPORTS": "وسائل النقل",
258
+ "TICKET_ONLY": "تذكرة فقط",
259
+ "RENT_A_CAR": "تأجير سيارة",
260
+ "TRANSFERS": "خدمات النقل",
261
+ "CRUISES": "رحلات بحرية",
262
+ "ONE_ACCOMMODATION": "إقامة واحدة",
263
+ "MULTIPLE_ACCOMMODATIONS": "إقامات متعددة",
264
+ "TRAVEL_CLASS_LABEL": "درجة السفر",
265
+ "TRAVEL_CLASS_PLACEHOLDER": "اختر درجة السفر",
266
+ "TRAVEL_TYPE_LABEL": "نوع السفر",
267
+ "TRAVEL_TYPE_PLACEHOLDER": "اختر نوع السفر",
268
+ "NATIONALITY_LABEL": "الجنسية",
269
+ "NATIONALITY_PLACEHOLDER": "اختر الجنسية",
270
+ "TRAVELERS_LABEL": "من المسافر؟",
271
+ "ADD_ROOM": "إضافة غرفة",
272
+ "REMOVE_ROOM": "إزالة غرفة",
273
+ "MAX_TRAVELERS_REACHED": "لقد وصلت إلى الحد الأقصى لعدد المسافرين",
274
+ "ADULTS": "البالغون",
275
+ "CHILDREN": "الأطفال",
276
+ "BABIES": "الرضع",
277
+ "CHOOSE_DATES": "اختر التواريخ",
278
+ "DEPARTURE_DATE": "تاريخ المغادرة",
279
+ "RETURN_DATE": "تاريخ العودة",
280
+ "CONFIRM": "تأكيد",
281
+ "TRAVELERS": "المسافرون"
282
+ },
283
+ "SRP": {
284
+ "NO_RESULTS": "لم يتم العثور على نتائج.",
285
+ "TOTAL_RESULTS_LABEL": "تم العثور على باقات",
286
+ "RESET": "إعادة تعيين",
287
+ "LUGGAGEINCLUDED": "الأمتعة مشمولة",
288
+ "CANCEL": "إلغاء",
289
+ "APPLY": "تطبيق",
290
+ "LOADING": "جارٍ التحميل...",
291
+ "SEARCHRESULTCTA": "عرض التفاصيل",
292
+ "SORTBY": "ترتيب حسب",
293
+ "PRICE_ASC": "السعر (من الأقل إلى الأعلى)",
294
+ "PRICE_DESC": "السعر (من الأعلى إلى الأقل)",
295
+ "DEPARTURE_ASC": "تاريخ المغادرة (الأقرب أولاً)",
296
+ "FILTERS": "عوامل التصفية",
297
+ "SHOW_ITINERARY": "عرض خط سير الرحلة",
298
+ "ITINERARY_TITLE": "ملخص رحلتك",
299
+ "DOSSIER_NUMBER": "رقم الملف",
300
+ "PACKAGE_PRICE_PER_PERSON": "سعر الباقة للشخص الواحد",
301
+ "TOTAL": "الإجمالي",
302
+ "DAY_BY_DAY": "رحلتك يوماً بيوم",
303
+ "START": "البداية",
304
+ "END": "النهاية",
305
+ "EXTENDED": "موسع",
306
+ "COMPACT": "مضغوط",
307
+ "LIST": "قائمة",
308
+ "SELECT": "اختيار",
309
+ "DEPARTURE": "المغادرة",
310
+ "RETURN": "العودة",
311
+ "DIRECT": "مباشر",
312
+ "STOPS": "محطات",
313
+ "STOP": "محطة",
314
+ "STOP_TIME": "مدة التوقف",
315
+ "ACCOMMODATION": "الإقامة",
316
+ "VIEW_DETAILS": "عرض التفاصيل",
317
+ "NIGHTS": "ليالٍ"
248
318
  }
249
319
  }
@@ -134,8 +134,11 @@
134
134
  "CHILD": "barn",
135
135
  "CHILDREN": "børn",
136
136
  "GENDER": "Tiltaleform",
137
+ "GENDER_ID": "Køn ifølge pas/ID-kort",
137
138
  "MALE": "Hr.",
139
+ "MALE_GENDER": "Mand",
138
140
  "FEMALE": "Fr.",
141
+ "FEMALE_GENDER": "Kvinde",
139
142
  "OTHER": "Andet",
140
143
  "MAIN_BOOKER": "Hovedbooker",
141
144
  "FIRST_NAME": "Fornavn",
@@ -245,5 +248,72 @@
245
248
  "LABEL_IDLE": "Print tilbud",
246
249
  "LABEL_CREATING": "Genererer tilbud…",
247
250
  "LABEL_PRINTING": "Genererer PDF…"
251
+ },
252
+ "QSM": {
253
+ "MULTIDESTINATION": "Flere destinationer",
254
+ "PACKAGES": "Pakkerejser",
255
+ "TRANSPORT_HOTEL": "Transport + hotel",
256
+ "ACCOMMODATION": "Indkvartering",
257
+ "TRANSPORTS": "Transport",
258
+ "TICKET_ONLY": "Kun billet",
259
+ "RENT_A_CAR": "Lej en bil",
260
+ "TRANSFERS": "Transportservice",
261
+ "CRUISES": "Krydstogter",
262
+ "ONE_ACCOMMODATION": "Én indkvartering",
263
+ "MULTIPLE_ACCOMMODATIONS": "Flere indkvarteringer",
264
+ "TRAVEL_CLASS_LABEL": "Rejseklasse",
265
+ "TRAVEL_CLASS_PLACEHOLDER": "Vælg rejseklasse",
266
+ "TRAVEL_TYPE_LABEL": "Rejsetype",
267
+ "TRAVEL_TYPE_PLACEHOLDER": "Vælg rejsetype",
268
+ "NATIONALITY_LABEL": "Nationalitet",
269
+ "NATIONALITY_PLACEHOLDER": "Vælg nationalitet",
270
+ "TRAVELERS_LABEL": "Hvem rejser?",
271
+ "ADD_ROOM": "Tilføj værelse",
272
+ "REMOVE_ROOM": "Fjern værelse",
273
+ "MAX_TRAVELERS_REACHED": "Du har nået det maksimale antal rejsende",
274
+ "ADULTS": "Voksne",
275
+ "CHILDREN": "Børn",
276
+ "BABIES": "Spædbørn",
277
+ "CHOOSE_DATES": "Vælg datoer",
278
+ "DEPARTURE_DATE": "Afrejsedato",
279
+ "RETURN_DATE": "Hjemrejsedato",
280
+ "CONFIRM": "Bekræft",
281
+ "TRAVELERS": "Rejsende"
282
+ },
283
+ "SRP": {
284
+ "NO_RESULTS": "Ingen resultater fundet.",
285
+ "TOTAL_RESULTS_LABEL": "Fundne pakker",
286
+ "RESET": "Nulstil",
287
+ "LUGGAGEINCLUDED": "Bagage inkluderet",
288
+ "CANCEL": "Annuller",
289
+ "APPLY": "Anvend",
290
+ "LOADING": "Indlæser...",
291
+ "SEARCHRESULTCTA": "Se detaljer",
292
+ "SORTBY": "Sorter efter",
293
+ "PRICE_ASC": "Pris (lav til høj)",
294
+ "PRICE_DESC": "Pris (høj til lav)",
295
+ "DEPARTURE_ASC": "Afrejsedato (snarest først)",
296
+ "FILTERS": "Filtre",
297
+ "SHOW_ITINERARY": "Vis rejseplan",
298
+ "ITINERARY_TITLE": "Din rejseoversigt",
299
+ "DOSSIER_NUMBER": "Sagsnummer",
300
+ "PACKAGE_PRICE_PER_PERSON": "pakkepris pr. person",
301
+ "TOTAL": "i alt",
302
+ "DAY_BY_DAY": "Din rejse dag for dag",
303
+ "START": "start",
304
+ "END": "slut",
305
+ "EXTENDED": "Udvidet",
306
+ "COMPACT": "Kompakt",
307
+ "LIST": "Liste",
308
+ "SELECT": "Vælg",
309
+ "DEPARTURE": "Afrejse",
310
+ "RETURN": "Hjemrejse",
311
+ "DIRECT": "Direkte",
312
+ "STOPS": "stop",
313
+ "STOP": "stop",
314
+ "STOP_TIME": "Skiftetid",
315
+ "ACCOMMODATION": "Indkvartering",
316
+ "VIEW_DETAILS": "Se detaljer",
317
+ "NIGHTS": "nætter"
248
318
  }
249
319
  }
@@ -134,8 +134,11 @@
134
134
  "CHILD": "Kind",
135
135
  "CHILDREN": "Kinder",
136
136
  "GENDER": "Anrede",
137
+ "GENDER_ID": "Geschlecht laut Reisepass/Personalausweis",
137
138
  "MALE": "Herr",
139
+ "MALE_GENDER": "Männlich",
138
140
  "FEMALE": "Frau",
141
+ "FEMALE_GENDER": "Weiblich",
139
142
  "OTHER": "Andere",
140
143
  "MAIN_BOOKER": "Hauptbucher",
141
144
  "FIRST_NAME": "Vorname",
@@ -245,5 +248,72 @@
245
248
  "LABEL_IDLE": "Angebot drucken",
246
249
  "LABEL_CREATING": "Angebot wird erstellt…",
247
250
  "LABEL_PRINTING": "PDF wird erstellt…"
251
+ },
252
+ "QSM": {
253
+ "MULTIDESTINATION": "Mehrere Reiseziele",
254
+ "PACKAGES": "Reisepakete",
255
+ "TRANSPORT_HOTEL": "Transport + Hotel",
256
+ "ACCOMMODATION": "Unterkunft",
257
+ "TRANSPORTS": "Transport",
258
+ "TICKET_ONLY": "Nur Ticket",
259
+ "RENT_A_CAR": "Mietwagen",
260
+ "TRANSFERS": "Transfers",
261
+ "CRUISES": "Kreuzfahrten",
262
+ "ONE_ACCOMMODATION": "Eine Unterkunft",
263
+ "MULTIPLE_ACCOMMODATIONS": "Mehrere Unterkünfte",
264
+ "TRAVEL_CLASS_LABEL": "Reiseklasse",
265
+ "TRAVEL_CLASS_PLACEHOLDER": "Reiseklasse auswählen",
266
+ "TRAVEL_TYPE_LABEL": "Reiseart",
267
+ "TRAVEL_TYPE_PLACEHOLDER": "Reiseart auswählen",
268
+ "NATIONALITY_LABEL": "Staatsangehörigkeit",
269
+ "NATIONALITY_PLACEHOLDER": "Staatsangehörigkeit auswählen",
270
+ "TRAVELERS_LABEL": "Wer reist?",
271
+ "ADD_ROOM": "Zimmer hinzufügen",
272
+ "REMOVE_ROOM": "Zimmer entfernen",
273
+ "MAX_TRAVELERS_REACHED": "Sie haben die maximale Anzahl an Reisenden erreicht",
274
+ "ADULTS": "Erwachsene",
275
+ "CHILDREN": "Kinder",
276
+ "BABIES": "Babys",
277
+ "CHOOSE_DATES": "Daten auswählen",
278
+ "DEPARTURE_DATE": "Abreisedatum",
279
+ "RETURN_DATE": "Rückreisedatum",
280
+ "CONFIRM": "Bestätigen",
281
+ "TRAVELERS": "Reisende"
282
+ },
283
+ "SRP": {
284
+ "NO_RESULTS": "Keine Ergebnisse gefunden.",
285
+ "TOTAL_RESULTS_LABEL": "Gefundene Pakete",
286
+ "RESET": "Zurücksetzen",
287
+ "LUGGAGEINCLUDED": "Gepäck inklusive",
288
+ "CANCEL": "Abbrechen",
289
+ "APPLY": "Anwenden",
290
+ "LOADING": "Wird geladen...",
291
+ "SEARCHRESULTCTA": "Details anzeigen",
292
+ "SORTBY": "Sortieren nach",
293
+ "PRICE_ASC": "Preis (aufsteigend)",
294
+ "PRICE_DESC": "Preis (absteigend)",
295
+ "DEPARTURE_ASC": "Abreisedatum (früheste zuerst)",
296
+ "FILTERS": "Filter",
297
+ "SHOW_ITINERARY": "Reiseverlauf anzeigen",
298
+ "ITINERARY_TITLE": "Ihre Reiseübersicht",
299
+ "DOSSIER_NUMBER": "Vorgangsnummer",
300
+ "PACKAGE_PRICE_PER_PERSON": "Paketpreis pro Person",
301
+ "TOTAL": "Gesamt",
302
+ "DAY_BY_DAY": "Ihre Reise Tag für Tag",
303
+ "START": "Start",
304
+ "END": "Ende",
305
+ "EXTENDED": "Erweitert",
306
+ "COMPACT": "Kompakt",
307
+ "LIST": "Liste",
308
+ "SELECT": "Auswählen",
309
+ "DEPARTURE": "Abreise",
310
+ "RETURN": "Rückreise",
311
+ "DIRECT": "Direkt",
312
+ "STOPS": "Stopps",
313
+ "STOP": "Stopp",
314
+ "STOP_TIME": "Umsteigezeit",
315
+ "ACCOMMODATION": "Unterkunft",
316
+ "VIEW_DETAILS": "Details anzeigen",
317
+ "NIGHTS": "Nächte"
248
318
  }
249
319
  }