diff --git a/commerce/src/inline-price.js b/commerce/src/inline-price.js index 7a3295eb..1a65454c 100644 --- a/commerce/src/inline-price.js +++ b/commerce/src/inline-price.js @@ -5,6 +5,20 @@ import { updatePlaceholder, } from './placeholder.js'; import { selectOffers, useService } from './utilities.js'; +import { GeoMap } from './settings'; + +// countries where tax is displayed for all segments by default +const DISPLAY_ALL_TAX_COUNTRIES = [GeoMap.uk, GeoMap.au, GeoMap.fr, GeoMap.at, GeoMap.be_en, GeoMap.be_fr, GeoMap.be_nl, GeoMap.bg, GeoMap.ch_de, GeoMap.ch_fr, GeoMap.ch_it, + GeoMap.cz, GeoMap.de, GeoMap.dk, GeoMap.ee, GeoMap.eg_ar, GeoMap.eg_en, GeoMap.es, GeoMap.fi, GeoMap.fr, GeoMap.gr_el, GeoMap.gr_en, GeoMap.hu, GeoMap.ie, GeoMap.it, GeoMap.lu_de, + GeoMap.lu_en, GeoMap.lu_fr, GeoMap.nl, GeoMap.no, GeoMap.pl, GeoMap.pt, GeoMap.ro, GeoMap.se, GeoMap.si, GeoMap.sk, GeoMap.tr, GeoMap.ua, GeoMap.id_en, GeoMap.id_id, + GeoMap.in_en, GeoMap.in_hi, GeoMap.jp, GeoMap.my_en, GeoMap.my_ms, GeoMap.nz, GeoMap.th_en, GeoMap.th_th]; +// countries where tax is displayed for some segments only by default +const DISPLAY_TAX_MAP = { + 'INDIVIDUAL_COM': [GeoMap.za, GeoMap.lt, GeoMap.lv, GeoMap.ng, GeoMap.sa_ar, GeoMap.sa_en, GeoMap.za, GeoMap.sg, GeoMap.kr], // individual + 'TEAM_COM': [GeoMap.za, GeoMap.lt, GeoMap.lv, GeoMap.ng, GeoMap.za, GeoMap.co, GeoMap.kr], // business + 'INDIVIDUAL_EDU': [GeoMap.lt, GeoMap.lv, GeoMap.sa_en, GeoMap.sea], // student + 'TEAM_EDU': [GeoMap.sea, GeoMap.kr], // school and uni +}; /** @type {Commerce.Price.PlaceholderConstructor} */ export class HTMLPriceSpanElement extends HTMLSpanElement { @@ -79,6 +93,44 @@ export class HTMLPriceSpanElement extends HTMLSpanElement { return this; } + /** + * Resolves default value of displayTax property, based on provided geo info and segments. + * @returns {boolean} + */ + resolveDisplayTaxForGeoAndSegment(country, language, customerSegment, marketSegment) { + const locale = `${country}_${language}`; + if (DISPLAY_ALL_TAX_COUNTRIES.includes(country) + || DISPLAY_ALL_TAX_COUNTRIES.includes(locale)) { + return true; + } + + const segmentConfig = DISPLAY_TAX_MAP[`${customerSegment}_${marketSegment}`]; + if (!segmentConfig) { + return false; + } + + if (segmentConfig.includes(country) || segmentConfig.includes(locale)) { + return true; + } + + return false; + } + + /** + * Resolves default value of displayTax property, based on provided geo info and segments extracted from offers object. + * @returns {boolean} + */ + async resolveDisplayTax(service, options) { + const [offerSelectors] = await service.resolveOfferSelectors(options); + const offers = selectOffers(await offerSelectors, options); + if (offers?.length) { + const { country, language } = options; + const offer = offers[0]; + const [marketSegment = ''] = offer.marketSegments; + return this.resolveDisplayTaxForGeoAndSegment(country, language, offer.customerSegment, marketSegment); + } + } + /** * Resolves associated osi via Wcs and renders price offer. * @param {Record} overrides @@ -92,6 +144,12 @@ export class HTMLPriceSpanElement extends HTMLSpanElement { this.placeholder ); if (!options.wcsOsi.length) return false; + + if (!this.placeholder.dataset.displayTax) { + // set default value for displayTax if not set neither in OST nor in price URL + options.displayTax = await this.resolveDisplayTax(service, options) || false; + } + const version = this.placeholder.togglePending(options); this.innerHTML = ''; const [promise] = service.resolveOfferSelectors(options); diff --git a/commerce/src/settings.js b/commerce/src/settings.js index 5a3e11ab..01106364 100644 --- a/commerce/src/settings.js +++ b/commerce/src/settings.js @@ -17,8 +17,14 @@ const DEFAULT_LOCALE = 'en_US'; const GeoMap = { ar: 'AR_es', + be_en: 'BE_en', + be_fr: 'BE_fr', + be_nl: 'BE_nl', br: 'BR_pt', ca: 'CA_en', + ch_de: 'CH_de', + ch_fr: 'CH_fr', + ch_it: 'CH_it', cl: 'CL_es', co: 'CO_es', la: 'DO_es', @@ -28,13 +34,22 @@ const GeoMap = { dk: 'DK_da', de: 'DE_de', ee: 'EE_et', + eg_ar: 'EG_ar', + eg_en: 'EG_en', es: 'ES_es', fr: 'FR_fr', + gr_el: 'GR_el', + gr_en: 'GR_en', ie: 'IE_en', il_he: 'IL_iw', it: 'IT_it', lv: 'LV_lv', lt: 'LT_lt', + lu_de: 'LU_de', + lu_en: 'LU_en', + lu_fr: 'LU_fr', + my_en: 'MY_en', + my_ms: 'MY_ms', hu: 'HU_hu', mt: 'MT_en', mena_en: 'DZ_en', @@ -56,9 +71,13 @@ const GeoMap = { ru: 'RU_ru', ua: 'UA_uk', au: 'AU_en', - in: 'IN_en', + in_en: 'IN_en', + in_hi: 'IN_hi', + id_en: 'ID_en', id_id: 'ID_in', nz: 'NZ_en', + sa_ar: 'SA_ar', + sa_en: 'SA_en', sg: 'SG_en', cn: 'CN_zh-Hans', tw: 'TW_zh-Hant', @@ -74,7 +93,8 @@ const GeoMap = { cis_en: 'AZ_en', cis_ru: 'AZ_ru', sea: 'SG_en', - th: 'TH_en', + th_en: 'TH_en', + th_th: 'TH_th', }; const HostEnv = Object.freeze({ @@ -211,4 +231,4 @@ function getSettings(config = {}) { }; } -export { HostEnv as MiloEnv, getLocaleSettings, getSettings }; +export { HostEnv as MiloEnv, getLocaleSettings, getSettings, GeoMap }; diff --git a/commerce/test/mocks/literals.json b/commerce/test/mocks/literals.json index c29f836e..0788a432 100644 --- a/commerce/test/mocks/literals.json +++ b/commerce/test/mocks/literals.json @@ -11,6 +11,488 @@ "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", "alternativePriceAriaLabel": "Alternatively at {alternativePrice}", "strikethroughAriaLabel": "Regularly at {strikethroughPrice}" - }], + }, + { + "lang": "ar", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/الشهر} YEAR {/العام} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {كل شهر} YEAR {كل عام} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {لكل ترخيص} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {لكل ترخيص} other {}}", + "freeLabel": "مجانًا", + "freeAriaLabel": "مجانًا", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "أو بدلاً من ذلك بقيمة {alternativePrice}", + "strikethroughAriaLabel": "بشكل منتظم بقيمة {strikethroughPrice}" + }, + { + "lang": "bg", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/мес.} YEAR {/год.} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {на месец} YEAR {на година} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {на лиценз} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {на лиценз} other {}}", + "freeLabel": "Безплатно", + "freeAriaLabel": "Безплатно", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Алтернативно на {alternativePrice}", + "strikethroughAriaLabel": "Редовно на {strikethroughPrice}" + }, + { + "lang": "cs", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/měsíc} YEAR {/rok} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {za měsíc} YEAR {za rok} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {za licenci} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {za licenci} other {}}", + "freeLabel": "Zdarma", + "freeAriaLabel": "Zdarma", + "taxExclusiveLabel": "{taxTerm, select, GST {bez daně ze zboží a služeb} VAT {bez DPH} TAX {bez daně} IVA {bez IVA} SST {bez SST} KDV {bez KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {včetně daně ze zboží a služeb} VAT {včetně DPH} TAX {včetně daně} IVA {včetně IVA} SST {včetně SST} KDV {včetně KDV} other {}}", + "alternativePriceAriaLabel": "Případně za {alternativePrice}", + "strikethroughAriaLabel": "Pravidelně za {strikethroughPrice}" + }, + { + "lang": "da", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/md} YEAR {/år} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {pr. måned} YEAR {pr. år} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {pr. licens} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {pr. licens} other {}}", + "freeLabel": "Gratis", + "freeAriaLabel": "Gratis", + "taxExclusiveLabel": "{taxTerm, select, GST {ekskl. GST} VAT {ekskl. moms} TAX {ekskl. skat} IVA {ekskl. IVA} SST {ekskl. SST} KDV {ekskl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {inkl. GST} VAT {inkl. moms} TAX {inkl. skat} IVA {inkl. IVA} SST {inkl. SST} KDV {inkl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternativt til {alternativePrice}", + "strikethroughAriaLabel": "Normalpris {strikethroughPrice}" + }, + { + "lang": "de", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/Monat} YEAR {/Jahr} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {pro Monat} YEAR {pro Jahr} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {pro Lizenz} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {pro Lizenz} other {}}", + "freeLabel": "Kostenlos", + "freeAriaLabel": "Kostenlos", + "taxExclusiveLabel": "{taxTerm, select, GST {zzgl. GST} VAT {zzgl. MwSt.} TAX {zzgl. Steuern} IVA {zzgl. IVA} SST {zzgl. SST} KDV {zzgl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {inkl. GST} VAT {inkl. MwSt.} TAX {inkl. Steuern} IVA {inkl. IVA} SST {inkl. SST} KDV {inkl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternativ: {alternativePrice}", + "strikethroughAriaLabel": "Regulär: {strikethroughPrice}" + }, + { + "lang": "et", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {kuus} YEAR {aastas} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {kuus} YEAR {aastas} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {litsentsi kohta} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {litsentsi kohta} other {}}", + "freeLabel": "Tasuta", + "freeAriaLabel": "Tasuta", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Teise võimalusena hinnaga {alternativePrice}", + "strikethroughAriaLabel": "Tavahind {strikethroughPrice}" + }, + { + "lang": "fi", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/kk} YEAR {/v} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {kuukausittain} YEAR {vuosittain} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {käyttöoikeutta kohti} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {käyttöoikeutta kohti} other {}}", + "freeLabel": "Maksuton", + "freeAriaLabel": "Maksuton", + "taxExclusiveLabel": "{taxTerm, select, GST {ilman GST:tä} VAT {ilman ALV:tä} TAX {ilman veroja} IVA {ilman IVA:ta} SST {ilman SST:tä} KDV {ilman KDV:tä} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {sis. GST:n} VAT {sis. ALV:n} TAX {sis. verot} IVA {sis. IVA:n} SST {sis. SST:n} KDV {sis. KDV:n} other {}}", + "alternativePriceAriaLabel": "Vaihtoehtoisesti hintaan {alternativePrice}", + "strikethroughAriaLabel": "Säännöllisesti hintaan {strikethroughPrice}" + }, + { + "lang": "fr", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mois} YEAR {/an} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {par mois} YEAR {par an} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {par licence} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {par licence} other {}}", + "freeLabel": "Gratuit", + "freeAriaLabel": "Gratuit", + "taxExclusiveLabel": "{taxTerm, select, GST {hors TPS} VAT {hors TVA} TAX {hors taxes} IVA {hors IVA} SST {hors SST} KDV {hors KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {TPS comprise} VAT {TVA comprise} TAX {taxes comprises} IVA {IVA comprise} SST {SST comprise} KDV {KDV comprise} other {}}", + "alternativePriceAriaLabel": "Autre prix {alternativePrice}", + "strikethroughAriaLabel": "Prix habituel {strikethroughPrice}" + }, + { + "lang": "he", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/חודש} YEAR {/שנה} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {לחודש} YEAR {לשנה} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {לרישיון} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {לרישיון} other {}}", + "freeLabel": "חינם", + "freeAriaLabel": "חינם", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "לחלופין ב-{alternativePrice}", + "strikethroughAriaLabel": "באופן קבוע ב-{strikethroughPrice}" + }, + { + "lang": "hu", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/hó} YEAR {/év} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {havonta} YEAR {évente} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {licencenként} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {licencenként} other {}}", + "freeLabel": "Ingyenes", + "freeAriaLabel": "Ingyenes", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Másik lehetőség: {alternativePrice}", + "strikethroughAriaLabel": "Általában {strikethroughPrice} áron" + }, + { + "lang": "it", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mese} YEAR {/anno} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {al mese} YEAR {all'anno} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {per licenza} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {per licenza} other {}}", + "freeLabel": "Gratuito", + "freeAriaLabel": "Gratuito", + "taxExclusiveLabel": "{taxTerm, select, GST {escl. GST} VAT {escl. IVA.} TAX {escl. imposte} IVA {escl. IVA} SST {escl. SST} KDV {escl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. IVA} TAX {incl. imposte} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "In alternativa a {alternativePrice}", + "strikethroughAriaLabel": "Regolarmente a {strikethroughPrice}" + }, + { + "lang": "ja", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/月} YEAR {/年} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {毎月} YEAR {毎年} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {ライセンスごと} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {ライセンスごと} other {}}", + "freeLabel": "無料", + "freeAriaLabel": "無料", + "taxExclusiveLabel": "{taxTerm, select, GST {GST 別} VAT {VAT 別} TAX {税別} IVA {IVA 別} SST {SST 別} KDV {KDV 別} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {GST 込} VAT {VAT 込} TAX {税込} IVA {IVA 込} SST {SST 込} KDV {KDV 込} other {}}", + "alternativePriceAriaLabel": "特別価格 : {alternativePrice}", + "strikethroughAriaLabel": "通常価格 : {strikethroughPrice}" + }, + { + "lang": "ko", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/월} YEAR {/년} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {월간} YEAR {연간} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {라이선스당} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {라이선스당} other {}}", + "freeLabel": "무료", + "freeAriaLabel": "무료", + "taxExclusiveLabel": "{taxTerm, select, GST {GST 제외} VAT {VAT 제외} TAX {세금 제외} IVA {IVA 제외} SST {SST 제외} KDV {KDV 제외} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {GST 포함} VAT {VAT 포함} TAX {세금 포함} IVA {IVA 포함} SST {SST 포함} KDV {KDV 포함} other {}}", + "alternativePriceAriaLabel": "또는 {alternativePrice}에", + "strikethroughAriaLabel": "또는 {alternativePrice}에" + }, + { + "lang": "lt", + "recurrenceLabel": "{recurrenceTerm, select, MONTH { per mėn.} YEAR { per metus} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per mėn.} YEAR {per metus} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {už licenciją} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {už licenciją} other {}}", + "freeLabel": "Nemokamai", + "freeAriaLabel": "Nemokamai", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Arba už {alternativePrice}", + "strikethroughAriaLabel": "Normaliai už {strikethroughPrice}" + }, + { + "lang": "lv", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {mēnesī} YEAR {gadā} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {mēnesī} YEAR {gadā} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {vienai licencei} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {vienai licencei} other {}}", + "freeLabel": "Bezmaksas", + "freeAriaLabel": "Bezmaksas", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternatīvi par {alternativePrice}", + "strikethroughAriaLabel": "Regulāri par {strikethroughPrice}" + }, + { + "lang": "nb", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mnd.} YEAR {/år} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per måned} YEAR {per år} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {per lisens} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {per lisens} other {}}", + "freeLabel": "Fri", + "freeAriaLabel": "Fri", + "taxExclusiveLabel": "{taxTerm, select, GST {ekskl. GST} VAT {ekskl. moms} TAX {ekskl. avgift} IVA {ekskl. IVA} SST {ekskl. SST} KDV {ekskl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {inkl. GST} VAT {inkl. moms} TAX {inkl. avgift} IVA {inkl. IVA} SST {inkl. SST} KDV {inkl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternativt til {alternativePrice}", + "strikethroughAriaLabel": "Regelmessig til {strikethroughPrice}" + }, + { + "lang": "nl", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mnd} YEAR {/jr} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per maand} YEAR {per jaar} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {per licentie} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {per licentie} other {}}", + "freeLabel": "Gratis", + "freeAriaLabel": "Gratis", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. btw} TAX {excl. belasting} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. btw} TAX {incl. belasting} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Nu {alternativePrice}", + "strikethroughAriaLabel": "Normaal {strikethroughPrice}" + }, + { + "lang": "pl", + "recurrenceLabel": "{recurrenceTerm, select, MONTH { / mies.} YEAR { / rok} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH { / miesiąc} YEAR { / rok} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {za licencję} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {za licencję} other {}}", + "freeLabel": "Bezpłatne", + "freeAriaLabel": "Bezpłatne", + "taxExclusiveLabel": "{taxTerm, select, GST {bez GST} VAT {bez VAT} TAX {netto} IVA {bez IVA} SST {bez SST} KDV {bez KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {z GST} VAT {z VAT} TAX {brutto} IVA {z IVA} SST {z SST} KDV {z KDV} other {}}", + "alternativePriceAriaLabel": "Lub za {alternativePrice}", + "strikethroughAriaLabel": "Cena zwykła: {strikethroughPrice}" + }, + { + "lang": "pt", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mês} YEAR {/ano} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {por mês} YEAR {por ano} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {por licença} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {por licença} other {}}", + "freeLabel": "Gratuito", + "freeAriaLabel": "Gratuito", + "taxExclusiveLabel": "{taxTerm, select, GST {ICMS não incluso} VAT {IVA não incluso} TAX {impostos não inclusos} IVA {IVA não incluso} SST { SST não incluso} KDV {KDV não incluso} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {ICMS incluso} VAT {IVA incluso} TAX {impostos inclusos} IVA {IVA incluso} SST {SST incluso} KDV {KDV incluso} other {}}", + "alternativePriceAriaLabel": "Ou a {alternativePrice}", + "strikethroughAriaLabel": "Preço normal: {strikethroughPrice}" + }, + { + "lang": "ro", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/lună} YEAR {/an} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {pe lună} YEAR {pe an} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {pe licență} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {pe licență} other {}}", + "freeLabel": "Gratuit", + "freeAriaLabel": "Gratuit", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternativ, la {alternativePrice}", + "strikethroughAriaLabel": "În mod normal, la {strikethroughPrice}" + }, + { + "lang": "ru", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/мес.} YEAR {/г.} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {в месяц} YEAR {в год} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {за лицензию} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {за лицензию} other {}}", + "freeLabel": "Бесплатно", + "freeAriaLabel": "Бесплатно", + "taxExclusiveLabel": "{taxTerm, select, GST {искл. налог на товары и услуги} VAT {искл. НДС} TAX {искл. налог} IVA {искл. ИВА} SST {искл. SST} KDV {искл. КДВ} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {вкл. налог на товары и услуги} VAT {вкл. НДС} TAX {вкл. налог} IVA {вкл. ИВА} SST {вкл. SST} KDV {вкл. КДВ} other {}}", + "alternativePriceAriaLabel": "Альтернативный вариант за {alternativePrice}", + "strikethroughAriaLabel": "Регулярно по цене {strikethroughPrice}" + }, + { + "lang": "sk", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mesiac} YEAR {/rok} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {za mesiac} YEAR {za rok} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {za licenciu} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {za licenciu} other {}}", + "freeLabel": "Zadarmo", + "freeAriaLabel": "Zadarmo", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Prípadne za {alternativePrice}", + "strikethroughAriaLabel": "Pravidelne za {strikethroughPrice}" + }, + { + "lang": "sl", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mesec} YEAR {/leto} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {na mesec} YEAR {na leto} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {na licenco} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {na licenco} other {}}", + "freeLabel": "Brezplačno", + "freeAriaLabel": "Brezplačno", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "Druga možnost je: {alternativePrice}", + "strikethroughAriaLabel": "Redno po {strikethroughPrice}" + }, + { + "lang": "sv", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mån} YEAR {/år} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per månad} YEAR {per år} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {per licens} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {per licens} other {}}", + "freeLabel": "Kostnadsfritt", + "freeAriaLabel": "Kostnadsfritt", + "taxExclusiveLabel": "{taxTerm, select, GST {exkl. GST} VAT {exkl. moms} TAX {exkl. skatt} IVA {exkl. IVA} SST {exkl. SST} KDV {exkl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {inkl. GST} VAT {inkl. moms} TAX {inkl. skatt} IVA {inkl. IVA} SST {inkl. SST} KDV {inkl. KDV} other {}}", + "alternativePriceAriaLabel": "Alternativt för {alternativePrice}", + "strikethroughAriaLabel": "Normalpris {strikethroughPrice}" + }, + { + "lang": "tr", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/ay} YEAR {/yıl} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {(aylık)} YEAR {(yıllık)} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {(lisans başına)} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {(lisans başına)} other {}}", + "freeLabel": "Ücretsiz", + "freeAriaLabel": "Ücretsiz", + "taxExclusiveLabel": "{taxTerm, select, GST {GST hariç} VAT {KDV hariç} TAX {vergi hariç} IVA {IVA hariç} SST {SST hariç} KDV {KDV hariç} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {GST dahil} VAT {KDV dahil} TAX {vergi dahil} IVA {IVA dahil} SST {SST dahil} KDV {KDV dahil} other {}}", + "alternativePriceAriaLabel": "Ya da {alternativePrice}", + "strikethroughAriaLabel": "Standart fiyat: {strikethroughPrice}" + }, + { + "lang": "uk", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/міс.} YEAR {/рік} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {на місяць} YEAR {на рік} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {за ліцензію} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {за ліцензію} other {}}", + "freeLabel": "Безкоштовно", + "freeAriaLabel": "Безкоштовно", + "taxExclusiveLabel": "{taxTerm, select, GST {без GST} VAT {без ПДВ} TAX {без податку} IVA {без IVA} SST {без SST} KDV {без KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {разом із GST} VAT {разом із ПДВ} TAX {разом із податком} IVA {разом з IVA} SST {разом із SST} KDV {разом із KDV} other {}}", + "alternativePriceAriaLabel": "Або за {alternativePrice}", + "strikethroughAriaLabel": "Звичайна ціна {strikethroughPrice}" + }, + { + "lang": "zh-hans", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/月} YEAR {/年} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {每月} YEAR {每年} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {每个许可证} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {每个许可证} other {}}", + "freeLabel": "免费", + "freeAriaLabel": "免费", + "taxExclusiveLabel": "{taxTerm, select, GST {excl. GST} VAT {excl. VAT} TAX {excl. tax} IVA {excl. IVA} SST {excl. SST} KDV {excl. KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {incl. GST} VAT {incl. VAT} TAX {incl. tax} IVA {incl. IVA} SST {incl. SST} KDV {incl. KDV} other {}}", + "alternativePriceAriaLabel": "或定价 {alternativePrice}", + "strikethroughAriaLabel": "正常价 {strikethroughPrice}" + }, + { + "lang": "zh-hant", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/月} YEAR {/年} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {每月} YEAR {每年} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {每個授權} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {每個授權} other {}}", + "freeLabel": "免費", + "freeAriaLabel": "免費", + "taxExclusiveLabel": "{taxTerm, select, GST {不含 GST} VAT {不含 VAT} TAX {不含稅} IVA {不含 IVA} SST {不含 SST} KDV {不含 KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {含 GST} VAT {含 VAT} TAX {含稅} IVA {含 IVA} SST {含 SST} KDV {含 KDV} other {}}", + "alternativePriceAriaLabel": "或者在 {alternativePrice}", + "strikethroughAriaLabel": "標準價格為 {strikethroughPrice}" + }, + { + "lang": "es", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/mes} YEAR {/año} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {al mes} YEAR {al año} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {por licencia} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {por licencia} other {}}", + "freeLabel": "Gratuito", + "freeAriaLabel": "Gratuito", + "taxExclusiveLabel": "{taxTerm, select, GST {GST no incluido} VAT {IVA no incluido} TAX {Impuestos no incluidos} IVA {IVA no incluido} SST {SST no incluido} KDV {KDV no incluido} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {GST incluido} VAT {IVA incluido} TAX {Impuestos incluidos} IVA {IVA incluido} SST {SST incluido} KDV {KDV incluido} other {}}", + "alternativePriceAriaLabel": "Alternativamente por {alternativePrice}", + "strikethroughAriaLabel": "Normalmente a {strikethroughPrice}" + }, + { + "lang": "in", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/bulan} YEAR {/tahun} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per bulan} YEAR {per tahun} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {per lisensi} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {per lisensi} other {}}", + "freeLabel": "Gratis", + "freeAriaLabel": "Gratis", + "taxExclusiveLabel": "{taxTerm, select, GST {tidak termasuk PBJ} VAT {tidak termasuk PPN} TAX {tidak termasuk pajak} IVA {tidak termasuk IVA} SST {tidak termasuk SST} KDV {tidak termasuk KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {termasuk PBJ} VAT {termasuk PPN} TAX {termasuk pajak} IVA {termasuk IVA} SST {termasuk SST} KDV {termasuk KDV} other {}}", + "alternativePriceAriaLabel": "Atau seharga {alternativePrice}", + "strikethroughAriaLabel": "Normalnya seharga {strikethroughPrice}" + }, + { + "lang": "vi", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/tháng} YEAR {/năm} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {mỗi tháng} YEAR {mỗi năm} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {mỗi giấy phép} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {mỗi giấy phép} other {}}", + "freeLabel": "Miễn phí", + "freeAriaLabel": "Miễn phí", + "taxExclusiveLabel": "{taxTerm, select, GST {chưa bao gồm thuế hàng hóa và dịch vụ} VAT {chưa bao gồm thuế GTGT} TAX {chưa bao gồm thuế} IVA {chưa bao gồm IVA} SST {chưa bao gồm SST} KDV {chưa bao gồm KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {(đã bao gồm thuế hàng hóa và dịch vụ)} VAT {(đã bao gồm thuế GTGT)} TAX {(đã bao gồm thuế)} IVA {(đã bao gồm IVA)} SST {(đã bao gồm SST)} KDV {(đã bao gồm KDV)} other {}}", + "alternativePriceAriaLabel": "Giá ưu đãi {alternativePrice}", + "strikethroughAriaLabel": "Giá thông thường {strikethroughPrice}" + }, + { + "lang": "th", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/เดือน} YEAR {/ปี} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {ต่อเดือน} YEAR {ต่อปี} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {ต่อสิทธิ์การใช้งาน} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {ต่อสิทธิ์การใช้งาน} other {}}", + "freeLabel": "ฟรี", + "freeAriaLabel": "ฟรี", + "taxExclusiveLabel": "{taxTerm, select, GST {ไม่รวมภาษี GST} VAT {ไม่รวม VAT} TAX {ไม่รวมภาษี} IVA {ไม่รวม IVA} SST {ไม่รวม SST} KDV {ไม่รวม KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {รวมภาษี GST} VAT {รวม VAT} TAX {รวมภาษี} IVA {รวม IVA} SST {รวม SST} KDV {รวม KDV} other {}}", + "alternativePriceAriaLabel": "ราคาพิเศษ {alternativePrice}", + "strikethroughAriaLabel": "ราคาปกติ {strikethroughPrice}" + }, + { + "lang": "el", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/μήνα} YEAR {/έτος} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {κάθε μήνα} YEAR {ανά έτος} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {ανά άδεια χρήσης} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {ανά άδεια χρήσης} other {}}", + "freeLabel": "Δωρεάν", + "freeAriaLabel": "Δωρεάν", + "taxExclusiveLabel": "{taxTerm, select, GST {(μη συμπεριλαμβανομένου GST)} VAT {(μη συμπεριλαμβανομένου ΦΠΑ)} TAX {(μη συμπεριλαμβανομένου φόρο)} IVA {(μη συμπεριλαμβανομένου IVA)} SST {(μη συμπεριλαμβανομένου SST)} KDV {(μη συμπεριλαμβανομένου KDV)} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {(συμπεριλαμβανομένου του GST)} VAT {(συμπεριλαμβανομένου ΦΠΑ)} TAX {(συμπεριλαμβανομένου του φόρου)} IVA {(συμπεριλαμβανομένου του IVA)} SST {(συμπεριλαμβανομένου του SST)} KDV {(συμπεριλαμβανομένου του KDV)} other {}}", + "alternativePriceAriaLabel": "Διαφορετικά, {alternativePrice}", + "strikethroughAriaLabel": "Κανονική τιμή {strikethroughPrice}" + }, + { + "lang": "fil", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/buwan} YEAR {/taon} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per buwan} YEAR {per taon} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {kada lisensya} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {kada lisensya} other {}}", + "freeLabel": "Libre", + "freeAriaLabel": "Libre", + "taxExclusiveLabel": "{taxTerm, select, GST {hindi kasama ang GST} VAT {hindi kasama ang VAT} TAX {hindi kasama ang Buwis} IVA {hindi kasama ang IVA} SST {hindi kasama ang SST} KDV {hindi kasama ang KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {kasama ang GST} VAT {kasama ang VAT} TAX {kasama ang Buwis} IVA {kasama ang IVA} SST {kasama ang SST} KDV {kasama ang KDV} other {}}", + "alternativePriceAriaLabel": "Alternatibong nasa halagang {alternativePrice}", + "strikethroughAriaLabel": "Regular na nasa halagang {strikethroughPrice}" + }, + { + "lang": "ms", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/bulan} YEAR {/tahun} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per bulan} YEAR {per tahun} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {setiap lesen} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {setiap lesen} other {}}", + "freeLabel": "Percuma", + "freeAriaLabel": "Percuma", + "taxExclusiveLabel": "{taxTerm, select, GST {kecuali GST} VAT {kecuali VAT} TAX {kecuali Cukai} IVA {kecuali IVA} SST {kecuali SST} KDV {kecuali KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {termasuk GST} VAT {termasuk VAT} TAX {termasuk Cukai} IVA {termasuk IVA} SST {termasuk SST} KDV {termasuk KDV} other {}}", + "alternativePriceAriaLabel": "Secara alternatif pada {alternativePrice}", + "strikethroughAriaLabel": "Biasanya pada {strikethroughPrice}" + }, + { + "lang": "hi", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/माह} YEAR {/वर्ष} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {per माह} YEAR {per वर्ष} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {प्रति लाइसेंस} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {प्रति लाइसेंस} other {}}", + "freeLabel": "फ़्री", + "freeAriaLabel": "फ़्री", + "taxExclusiveLabel": "{taxTerm, select, GST {GST अतिरिक्त} VAT {VAT अतिरिक्त} TAX {कर अतिरिक्त} IVA {IVA अतिरिक्त} SST {SST अतिरिक्त} KDV {KDV अतिरिक्त} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {GST सहित} VAT {VAT सहित} TAX {कर सहित} IVA {IVA सहित} SST {SST सहित} KDV {KDV सहित} other {}}", + "alternativePriceAriaLabel": "वैकल्पिक रूप से इस पर {alternativePrice}", + "strikethroughAriaLabel": "नियमित रूप से इस पर {strikethroughPrice}" + }, + { + "lang": "iw", + "recurrenceLabel": "{recurrenceTerm, select, MONTH {/חודש} YEAR {/שנה} other {}}", + "recurrenceAriaLabel": "{recurrenceTerm, select, MONTH {לחודש} YEAR {לשנה} other {}}", + "perUnitLabel": "{perUnit, select, LICENSE {לרישיון} other {}}", + "perUnitAriaLabel": "{perUnit, select, LICENSE {לרישיון} other {}}", + "freeLabel": "חינם", + "freeAriaLabel": "חינם", + "taxExclusiveLabel": "{taxTerm, select, GST {ללא GST} VAT {ללא מע\"מ} TAX {ללא מס} IVA {ללא IVA} SST {ללא SST} KDV {ללא KDV} other {}}", + "taxInclusiveLabel": "{taxTerm, select, GST {כולל GST} VAT {כולל מע\"מ} TAX {כולל מס} IVA {כולל IVA} SST {כולל SST} KDV {כולל KDV} other {}}", + "alternativePriceAriaLabel": "לחלופין ב-{alternativePrice}", + "strikethroughAriaLabel": "באופן קבוע ב-{strikethroughPrice}" + } + ], ":type": "sheet" } diff --git a/commerce/test/mocks/offers.json b/commerce/test/mocks/offers.json index a84148ca..fe19762e 100644 --- a/commerce/test/mocks/offers.json +++ b/commerce/test/mocks/offers.json @@ -881,5 +881,155 @@ "language": "MULT", "merchant": "ADOBE" } - ] + ], + "abm-team-gov-mult": [ + { + "offerId": "DAC628518DDD843D4D19A8BF7D8FF1FE", + "priceDetails": { + "price": 89.99, + "priceWithoutTax": 0.0, + "priceWithoutDiscountAndTax": 89.99, + "usePrecision": true, + "formatString": "'US$'#,##0.00", + "taxDisplay": "TAX_EXCLUSIVE", + "taxTerm": "TAX" + }, + "productArrangementCode": "ccle_direct_indirect_team", + "productArrangement": { + "productFamily": "CC_ALL_APPS" + }, + "buyingProgram": "RETAIL", + "commitment": "YEAR", + "term": "MONTHLY", + "customerSegment": "TEAM", + "marketSegments": [ + "GOV" + ], + "salesChannel": "DIRECT", + "offerType": "TRIAL", + "pricePoint": "TRIAL_14_DAY_TWP_TEAM_DIRECT_CCT_ALL_APPS_COM", + "language": "MULT", + "merchant": "ADOBE" + } + ], + "individual-mult": [ + { + "offerId": "DAC628518DDD843D4D19A8BF7D8FF1FA", + "priceDetails": { + "price": 1.99, + "priceWithoutTax": 0.0, + "priceWithoutDiscountAndTax": 1.99, + "usePrecision": true, + "formatString": "'US$'#,##0.00", + "taxDisplay": "TAX_EXCLUSIVE", + "taxTerm": "TAX" + }, + "productArrangementCode": "ccle_direct_indirect_team", + "productArrangement": { + "productFamily": "CC_ALL_APPS" + }, + "buyingProgram": "RETAIL", + "commitment": "YEAR", + "term": "MONTHLY", + "customerSegment": "INDIVIDUAL", + "marketSegments": [ + "COM" + ], + "salesChannel": "DIRECT", + "offerType": "BASE", + "pricePoint": "REGULAR", + "language": "MULT", + "merchant": "ADOBE" + } + ], + "business-mult": [ + { + "offerId": "DAC628518DDD843D4D19A8BF7D8FF1FB", + "priceDetails": { + "price": 1.99, + "priceWithoutTax": 0.0, + "priceWithoutDiscountAndTax": 1.99, + "usePrecision": true, + "formatString": "'US$'#,##0.00", + "taxDisplay": "TAX_EXCLUSIVE", + "taxTerm": "TAX" + }, + "productArrangementCode": "ccle_direct_indirect_team", + "productArrangement": { + "productFamily": "CC_ALL_APPS" + }, + "buyingProgram": "RETAIL", + "commitment": "YEAR", + "term": "MONTHLY", + "customerSegment": "TEAM", + "marketSegments": [ + "COM" + ], + "salesChannel": "DIRECT", + "offerType": "BASE", + "pricePoint": "REGULAR", + "language": "MULT", + "merchant": "ADOBE" + } + ], + "student-mult": [ + { + "offerId": "DAC628518DDD843D4D19A8BF7D8FF1FC", + "priceDetails": { + "price": 1.99, + "priceWithoutTax": 0.0, + "priceWithoutDiscountAndTax": 1.99, + "usePrecision": true, + "formatString": "'US$'#,##0.00", + "taxDisplay": "TAX_EXCLUSIVE", + "taxTerm": "TAX" + }, + "productArrangementCode": "ccle_direct_indirect_team", + "productArrangement": { + "productFamily": "CC_ALL_APPS" + }, + "buyingProgram": "RETAIL", + "commitment": "YEAR", + "term": "MONTHLY", + "customerSegment": "INDIVIDUAL", + "marketSegments": [ + "EDU" + ], + "salesChannel": "DIRECT", + "offerType": "BASE", + "pricePoint": "REGULAR", + "language": "MULT", + "merchant": "ADOBE" + } + ], + "university-mult": [ + { + "offerId": "DAC628518DDD843D4D19A8BF7D8FF1FD", + "priceDetails": { + "price": 1.99, + "priceWithoutTax": 0.0, + "priceWithoutDiscountAndTax": 1.99, + "usePrecision": true, + "formatString": "'US$'#,##0.00", + "taxDisplay": "TAX_EXCLUSIVE", + "taxTerm": "TAX" + }, + "productArrangementCode": "ccle_direct_indirect_team", + "productArrangement": { + "productFamily": "CC_ALL_APPS" + }, + "buyingProgram": "RETAIL", + "commitment": "YEAR", + "term": "MONTHLY", + "customerSegment": "TEAM", + "marketSegments": [ + "EDU" + ], + "salesChannel": "DIRECT", + "offerType": "BASE", + "pricePoint": "REGULAR", + "language": "MULT", + "merchant": "ADOBE" + } + ] } diff --git a/commerce/test/price.test.js b/commerce/test/price.test.js index 6ab2d2dc..b457febe 100644 --- a/commerce/test/price.test.js +++ b/commerce/test/price.test.js @@ -286,6 +286,390 @@ describe('class "InlinePrice"', () => { ]); }); }); + + describe('default display tax', () => { + const SEGMENTS = ['individual', 'business', 'student', 'university']; + const TESTS = [ + { + locale: 'AE_ar', + expected: [false, false, false, false] + }, + { + locale: 'AE_en', + expected: [false, false, false, false] + }, + { + locale: 'ZA_en', + expected: [true, true, false, false] + }, + { + locale: 'AT_de', + expected: [true, true, true, true] + }, + { + locale: 'BE_en', + expected: [true, true, true, true] + }, + { + locale: 'BE_fr', + expected: [true, true, true, true] + }, + { + locale: 'BE_nl', + expected: [true, true, true, true] + }, + { + locale: 'BG_bg', + expected: [true, true, true, true] + }, + { + locale: 'CH_de', + expected: [true, true, true, true] + }, + { + locale: 'CH_fr', + expected: [true, true, true, true] + }, + { + locale: 'CH_it', + expected: [true, true, true, true] + }, + { + locale: 'AZ_en', + expected: [false, false, false, false] + }, + { + locale: 'AZ_ru', + expected: [false, false, false, false] + }, + { + locale: 'CZ_cs', + expected: [true, true, true, true] + }, + { + locale: 'DE_de', + expected: [true, true, true, true] + }, + { + locale: 'DK_da', + expected: [true, true, true, true] + }, + { + locale: 'EE_et', + expected: [true, true, true, true] + }, + { + locale: 'EG_ar', + expected: [true, true, true, true] + }, + { + locale: 'EG_en', + expected: [true, true, true, true] + }, + { + locale: 'ES_es', + expected: [true, true, true, true] + }, + { + locale: 'FI_fi', + expected: [true, true, true, true] + }, + { + locale: 'FR_fr', + expected: [true, true, true, true] + }, + { + locale: 'GR_el', + expected: [true, true, true, true] + }, + { + locale: 'GR_en', + expected: [true, true, true, true] + }, + { + locale: 'HU_hu', + expected: [true, true, true, true] + }, + { + locale: 'IE_en', + expected: [true, true, true, true] + }, + { + locale: 'IL_en', + expected: [false, false, false, false] + }, + { + locale: 'IL_iw', + expected: [false, false, false, false] + }, + { + locale: 'IT_it', + expected: [true, true, true, true] + }, + { + locale: 'KW_ar', + expected: [false, false, false, false] + }, + { + locale: 'KW_en', + expected: [false, false, false, false] + }, + { + locale: 'LT_lt', + expected: [true, true, true, false] + }, + { + locale: 'LU_de', + expected: [true, true, true, true] + }, + { + locale: 'LU_en', + expected: [true, true, true, true] + }, + { + locale: 'LU_fr', + expected: [true, true, true, true] + }, + { + locale: 'LV_lv', + expected: [true, true, true, false] + }, + { + locale: 'DZ_ar', + expected: [false, false, false, false] + }, + { + locale: 'DZ_en', + expected: [false, false, false, false] + }, + { + locale: 'NG_en', + expected: [true, true, false, false] + }, + { + locale: 'NL_nl', + expected: [true, true, true, true] + }, + { + locale: 'NO_nb', + expected: [true, true, true, true] + }, + { + locale: 'PL_pl', + expected: [true, true, true, true] + }, + { + locale: 'PT_pt', + expected: [true, true, true, true] + }, + { + locale: 'QA_ar', + expected: [false, false, false, false] + }, + { + locale: 'QA_en', + expected: [false, false, false, false] + }, + { + locale: 'RO_ro', + expected: [true, true, true, true] + }, + { + locale: 'RU_ru', + expected: [false, false, false, false] + }, + { + locale: 'SA_ar', + expected: [true, false, false, false] + }, + { + locale: 'SA_en', + expected: [true, false, true, false] + }, + { + locale: 'SE_sv', + expected: [true, true, true, true] + }, + { + locale: 'SI_sl', + expected: [true, true, true, true] + }, + { + locale: 'SK_sk', + expected: [true, true, true, true] + }, + { + locale: 'TR_tr', + expected: [true, true, true, true] + }, + { + locale: 'UA_uk', + expected: [true, true, true, true] + }, + { + locale: 'ZA_en', + expected: [true, true, false, false] + }, + { + locale: 'AU_en', + expected: [true, true, true, true] + }, + { + locale: 'HK_en', + expected: [false, false, false, false] + }, + { + locale: 'ID_en', + expected: [true, true, true, true] + }, + { + locale: 'ID_in', + expected: [true, true, true, true] + }, + { + locale: 'IN_en', + expected: [true, true, true, true] + }, + { + locale: 'IN_hi', + expected: [true, true, true, true] + }, + { + locale: 'JP_ja', + expected: [true, true, true, true] + }, + { + locale: 'KR_ko', + expected: [true, true, false, true] + }, + { + locale: 'MY_en', + expected: [true, true, true, true] + }, + { + locale: 'MY_ms', + expected: [true, true, true, true] + }, + { + locale: 'NZ_en', + expected: [true, true, true, true] + }, + { + locale: 'PH_en', + expected: [false, false, false, false] + }, + { + locale: 'PH_fil', + expected: [false, false, false, false] + }, + { + locale: 'SG_en', + expected: [true, false, true, true] + }, + { + locale: 'TH_en', + expected: [true, true, true, true] + }, + { + locale: 'TH_th', + expected: [true, true, true, true] + }, + { + locale: 'VN_en', + expected: [false, false, false, false] + }, + { + locale: 'VN_vi', + expected: [false, false, false, false] + }, + { + locale: 'AR_es', + expected: [false, false, false, false] + }, + { + locale: 'BR_pt', + expected: [false, false, false, false] + }, + { + locale: 'CA_en', + expected: [false, false, false, false] + }, + { + locale: 'CA_fr', + expected: [false, false, false, false] + }, + { + locale: 'CL_es', + expected: [false, false, false, false] + }, + { + locale: 'CO_es', + expected: [false, true, false, false] + }, + { + locale: 'CR_es', + expected: [false, false, false, false] + }, + { + locale: 'EC_es', + expected: [false, false, false, false] + }, + { + locale: 'GT_es', + expected: [false, false, false, false] + }, + { + locale: 'LA_es', + expected: [false, false, false, false] + }, + { + locale: 'MX_es', + expected: [false, false, false, false] + }, + { + locale: 'PE_es', + expected: [false, false, false, false] + }, + { + locale: 'PR_es', + expected: [false, false, false, false] + }, + { + locale: 'US_en', + expected: [false, false, false, false] + }, + ]; + + TESTS.forEach((test) => { + SEGMENTS.forEach((segment, index) => { + it(`renders price with tax info for "${test.locale}" and "${segment}"`, async () => { + const config = mockConfig({}, { prefix: test.locale}); + const service = await initService(config, true); + const inlinePrice = mockInlinePrice(segment); + inlinePrice.removeAttribute('data-display-tax'); + await inlinePrice.onceSettled(); + const priceTaxElement = inlinePrice.querySelector('.price-tax-inclusivity'); + if (test.expected[index]) { + const taxExclusiveLabel = service.literals.price.taxExclusiveLabel; + const taxLabel = taxExclusiveLabel.match(/TAX \{(.*?)\}/)[1] + expect(priceTaxElement.textContent).to.equal(taxLabel); + } else { + expect(priceTaxElement.classList.contains('disabled')).to.be.true; + } + }); + }); + }); + + it('renders price with tax info for AE, default tax value', async () => { + await initService(mockConfig(), true); + const inlinePrice = mockInlinePrice('abm-team-gov'); + inlinePrice.removeAttribute('data-display-tax'); + inlinePrice.dataset.country = 'AE'; + inlinePrice.dataset.language = 'en'; + await inlinePrice.onceSettled(); + expect(inlinePrice.textContent).equal('US$89.99/mo'); + }); + }); }); describe('commerce service', () => { diff --git a/web-components/src/bodyScrollLock.js b/web-components/src/bodyScrollLock.js new file mode 100644 index 00000000..8169dcb8 --- /dev/null +++ b/web-components/src/bodyScrollLock.js @@ -0,0 +1,49 @@ +/* +Enables body scroll locking (for iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox) without breaking scrolling of a target element. +Usage example: when opening a modal, disable body scroll by calling enableBodyScroll, and enable it back when closing the modal by calling disableBodyScroll. +*/ + +const isIosDevice = + typeof window !== 'undefined' && + window.navigator && + window.navigator.platform && + (/iP(ad|hone|od)/.test(window.navigator.platform) || + (window.navigator.platform === 'MacIntel' && + window.navigator.maxTouchPoints > 1)); +let documentListenerAdded = false; +let previousBodyOverflowSetting; + +export const disableBodyScroll = (targetElement) => { + if (!targetElement) return; + if (isIosDevice) { + document.body.style.position = 'fixed'; + targetElement.ontouchmove = (event) => { + if (event.targetTouches.length === 1) { + event.stopPropagation(); + } + }; + if (!documentListenerAdded) { + document.addEventListener('touchmove', (e) => e.preventDefault()); + documentListenerAdded = true; + } + } else { + previousBodyOverflowSetting = document.body.style.overflow; + document.body.style.overflow = 'hidden'; + } +}; + +export const enableBodyScroll = (targetElement) => { + if (!targetElement) return; + if (isIosDevice) { + targetElement.ontouchstart = null; + targetElement.ontouchmove = null; + document.body.style.position = ''; + document.removeEventListener('touchmove', (e) => e.preventDefault()); + documentListenerAdded = false; + } else { + if (previousBodyOverflowSetting !== undefined) { + document.body.style.overflow = previousBodyOverflowSetting; + previousBodyOverflowSetting = undefined; + } + } +}; diff --git a/web-components/src/deeplink.js b/web-components/src/deeplink.js index f288f9ab..12056a1e 100644 --- a/web-components/src/deeplink.js +++ b/web-components/src/deeplink.js @@ -54,6 +54,7 @@ export function pushState(state) { */ export function deeplink(callback) { const handler = () => { + if (!window.location.hash.includes('=')) return; const state = parseState(window.location.hash); callback(state); }; diff --git a/web-components/src/global.css.js b/web-components/src/global.css.js index 878d9e96..89290c89 100644 --- a/web-components/src/global.css.js +++ b/web-components/src/global.css.js @@ -150,15 +150,7 @@ merch-card-collection > div[slot] p { justify-content: center; justify-items: stretch; gap: var(--consonant-merch-spacing-m); -} - -@media screen and ${DESKTOP_UP} { - .one-merch-card, - .two-merch-cards, - .three-merch-cards, - .four-merch-cards { - padding: var(--spacing-m); - } + padding: var(--spacing-m); } merch-card.background-opacity-70 { @@ -564,6 +556,7 @@ div[slot='bg-image'] img { @media screen and ${MOBILE_LANDSCAPE} { :root { --consonant-merch-card-mini-compare-chart-width: 142px; + --consonant-merch-card-segment-width: 276px; --consonant-merch-card-mini-compare-chart-wide-width: 302px; --consonant-merch-card-special-offers-width: 302px; --consonant-merch-card-twp-width: 300px; @@ -576,6 +569,7 @@ div[slot='bg-image'] img { :root { --consonant-merch-card-catalog-width: 302px; --consonant-merch-card-plans-width: 302px; + --consonant-merch-card-segment-width: 276px; --consonant-merch-card-mini-compare-chart-width: 178px; --consonant-merch-card-mini-compare-chart-wide-width: 302px; --consonant-merch-card-special-offers-width: 302px; @@ -588,6 +582,7 @@ div[slot='bg-image'] img { :root { --consonant-merch-card-catalog-width: 276px; --consonant-merch-card-plans-width: 276px; + --consonant-merch-card-segment-width: 302px; --consonant-merch-card-inline-heading-width: 378px; --consonant-merch-card-product-width: 378px; --consonant-merch-card-image-width: 378px; diff --git a/web-components/src/merch-card.css.js b/web-components/src/merch-card.css.js index 5b65add3..a6433fc7 100644 --- a/web-components/src/merch-card.css.js +++ b/web-components/src/merch-card.css.js @@ -204,6 +204,8 @@ export const styles = css` gap: var(--consonant-merch-spacing-xxs); align-items: center; flex: 1; + height: 100%; + line-height: normal; } .secure-transaction-label::before { diff --git a/web-components/src/merch-quantity-select.css.js b/web-components/src/merch-quantity-select.css.js index 94d4970d..8a570ddf 100644 --- a/web-components/src/merch-quantity-select.css.js +++ b/web-components/src/merch-quantity-select.css.js @@ -47,12 +47,12 @@ export const styles = css` border-right: none; padding-inline-start: 12px; box-sizing: border-box; + -moz-appearance: textfield; } .text-field-input::-webkit-inner-spin-button, .text-field-input::-webkit-outer-spin-button { margin: 0; - -moz-appearance: textfield; -webkit-appearance: none; } diff --git a/web-components/src/sidenav/merch-sidenav.js b/web-components/src/sidenav/merch-sidenav.js index cc8062a3..4f1bd7f1 100644 --- a/web-components/src/sidenav/merch-sidenav.js +++ b/web-components/src/sidenav/merch-sidenav.js @@ -5,6 +5,7 @@ import '../merch-search.js'; import './merch-sidenav-list.js'; import './merch-sidenav-checkbox-group.js'; import { SPECTRUM_MOBILE_LANDSCAPE, TABLET_DOWN } from '../media.js'; +import { disableBodyScroll, enableBodyScroll } from '../bodyScrollLock.js'; document.addEventListener('sp-opened', () => { document.body.classList.add('merch-modal'); @@ -140,6 +141,7 @@ export class MerchSideNav extends LitElement { openModal() { this.updateComplete.then(async () => { + disableBodyScroll(this.dialog); const options = { trigger: this.#target, notImmediatelyClosable: true, @@ -151,6 +153,7 @@ export class MerchSideNav extends LitElement { ); overlay.addEventListener('close', () => { this.modal = false; + enableBodyScroll(this.dialog); }); this.shadowRoot.querySelector('sp-theme').append(overlay); });