diff --git a/public/intl/messages/ar-SA.json b/public/intl/messages/ar-SA.json index 98f937fed..85ae17623 100644 --- a/public/intl/messages/ar-SA.json +++ b/public/intl/messages/ar-SA.json @@ -171,6 +171,9 @@ "manager": "مدير", "max": "الحد الأقصى", "maximize": "توسيع", + "match": "تطابق", + "match-all": "الكل (AND)", + "match-any": "أي (OR)", "medium": "وسيط", "member": "عضو", "members": "الأعضاء", diff --git a/public/intl/messages/be-BY.json b/public/intl/messages/be-BY.json index 8cbdd1046..ef13ffecf 100644 --- a/public/intl/messages/be-BY.json +++ b/public/intl/messages/be-BY.json @@ -171,6 +171,9 @@ "manager": "Кіраўнік", "max": "Максімум", "maximize": "Разгарнуць", + "match": "Адпаведнасць", + "match-all": "Усе (AND)", + "match-any": "Любы (OR)", "medium": "Сярэдні", "member": "Удзельнік", "members": "Удзельнікі", diff --git a/public/intl/messages/bg-BG.json b/public/intl/messages/bg-BG.json index 2edf2ae76..b7ab4d1b3 100644 --- a/public/intl/messages/bg-BG.json +++ b/public/intl/messages/bg-BG.json @@ -171,6 +171,9 @@ "manager": "Мениджър", "max": "Максимум", "maximize": "Разшири", + "match": "Съвпадение", + "match-all": "Всички (AND)", + "match-any": "Някои (OR)", "medium": "Среден", "member": "Член", "members": "Членове", diff --git a/public/intl/messages/bn-BD.json b/public/intl/messages/bn-BD.json index fcc263cb8..85dd82f2e 100644 --- a/public/intl/messages/bn-BD.json +++ b/public/intl/messages/bn-BD.json @@ -171,6 +171,9 @@ "manager": "পরিচালক", "max": "সর্বাধিক", "maximize": "বিস্তৃত করুন", + "match": "মিলান", + "match-all": "সব (AND)", + "match-any": "যেকোনো (OR)", "medium": "মাঝারি", "member": "সদস্য", "members": "সদস্যগণ", diff --git a/public/intl/messages/bs-BA.json b/public/intl/messages/bs-BA.json index eb55ff438..547ae7836 100644 --- a/public/intl/messages/bs-BA.json +++ b/public/intl/messages/bs-BA.json @@ -171,6 +171,9 @@ "manager": "Menadžer", "max": "Maks", "maximize": "Proširi", + "match": "Podudaranje", + "match-all": "Sve (AND)", + "match-any": "Bilo koje (OR)", "medium": "Srednje", "member": "Član", "members": "Članovi", diff --git a/public/intl/messages/ca-ES.json b/public/intl/messages/ca-ES.json index 30b66451c..e73ba612f 100644 --- a/public/intl/messages/ca-ES.json +++ b/public/intl/messages/ca-ES.json @@ -171,6 +171,9 @@ "manager": "Responsable", "max": "Màx", "maximize": "Expandeix", + "match": "Coincidència", + "match-all": "Tots (AND)", + "match-any": "Qualsevol (OR)", "medium": "Mitjà", "member": "Membre", "members": "Membres", diff --git a/public/intl/messages/cs-CZ.json b/public/intl/messages/cs-CZ.json index eacaee4ac..ac15c67a1 100644 --- a/public/intl/messages/cs-CZ.json +++ b/public/intl/messages/cs-CZ.json @@ -171,6 +171,9 @@ "manager": "Správce", "max": "Max", "maximize": "Rozbalit", + "match": "Shoda", + "match-all": "Vše (AND)", + "match-any": "Jakýkoli (OR)", "medium": "Střední", "member": "Člen", "members": "Členové", diff --git a/public/intl/messages/da-DK.json b/public/intl/messages/da-DK.json index 16e16128d..57fd08376 100644 --- a/public/intl/messages/da-DK.json +++ b/public/intl/messages/da-DK.json @@ -171,6 +171,9 @@ "manager": "Leder", "max": "Maks", "maximize": "Udvid", + "match": "Match", + "match-all": "Alle (AND)", + "match-any": "Enhver (OR)", "medium": "Medie", "member": "Medlem", "members": "Medlemmer", diff --git a/public/intl/messages/de-CH.json b/public/intl/messages/de-CH.json index 6125b2386..f309f9e54 100644 --- a/public/intl/messages/de-CH.json +++ b/public/intl/messages/de-CH.json @@ -171,6 +171,9 @@ "manager": "Verwalter", "max": "Max", "maximize": "Uusklappe", + "match": "Übereinstimmung", + "match-all": "Alle (AND)", + "match-any": "Beliebige (OR)", "medium": "Medium", "member": "Mitglied", "members": "Mitglieder", diff --git a/public/intl/messages/de-DE.json b/public/intl/messages/de-DE.json index c059a1a5c..bf17b131e 100644 --- a/public/intl/messages/de-DE.json +++ b/public/intl/messages/de-DE.json @@ -171,6 +171,9 @@ "manager": "Verwaltung", "max": "Max", "maximize": "Erweitern", + "match": "Übereinstimmung", + "match-all": "Alle (AND)", + "match-any": "Beliebige (OR)", "medium": "Medium", "member": "Mitglied", "members": "Mitglieder", diff --git a/public/intl/messages/el-GR.json b/public/intl/messages/el-GR.json index 4a0b36330..8450f3a6f 100644 --- a/public/intl/messages/el-GR.json +++ b/public/intl/messages/el-GR.json @@ -171,6 +171,9 @@ "manager": "Διαχειριστής", "max": "Μέγ", "maximize": "Expand", + "match": "Αντιστοίχιση", + "match-all": "Όλα (AND)", + "match-any": "Οποιοδήποτε (OR)", "medium": "Μέσο", "member": "Μέλος", "members": "Μέλη", diff --git a/public/intl/messages/en-GB.json b/public/intl/messages/en-GB.json index 33d676e73..57b8ea619 100644 --- a/public/intl/messages/en-GB.json +++ b/public/intl/messages/en-GB.json @@ -171,6 +171,9 @@ "manager": "Manager", "max": "Max", "maximize": "Expand", + "match": "Match", + "match-all": "All (AND)", + "match-any": "Any (OR)", "medium": "Medium", "member": "Member", "members": "Members", diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json index 9ff141bd7..33704d17d 100644 --- a/public/intl/messages/en-US.json +++ b/public/intl/messages/en-US.json @@ -170,6 +170,9 @@ "manage": "Manage", "manager": "Manager", "max": "Max", + "match": "Match", + "match-all": "All (AND)", + "match-any": "Any (OR)", "maximize": "Maximize", "medium": "Medium", "member": "Member", diff --git a/public/intl/messages/es-ES.json b/public/intl/messages/es-ES.json index 856d6977a..11031f818 100644 --- a/public/intl/messages/es-ES.json +++ b/public/intl/messages/es-ES.json @@ -171,6 +171,9 @@ "manager": "Gerente", "max": "Máximo", "maximize": "Expandir", + "match": "Coincidencia", + "match-all": "Todo (AND)", + "match-any": "Cualquiera (OR)", "medium": "Medio", "member": "Miembro", "members": "Miembros", diff --git a/public/intl/messages/fa-IR.json b/public/intl/messages/fa-IR.json index 49ba05391..ee072c74c 100644 --- a/public/intl/messages/fa-IR.json +++ b/public/intl/messages/fa-IR.json @@ -171,6 +171,9 @@ "manager": "مدیر", "max": "حداکثر", "maximize": "گسترش", + "match": "تطابق", + "match-all": "همه (AND)", + "match-any": "هر (OR)", "medium": "متوسط", "member": "عضو", "members": "اعضا", diff --git a/public/intl/messages/fi-FI.json b/public/intl/messages/fi-FI.json index 7b802535c..63da45902 100644 --- a/public/intl/messages/fi-FI.json +++ b/public/intl/messages/fi-FI.json @@ -171,6 +171,9 @@ "manager": "Päällikkö", "max": "Maksimi", "maximize": "Laajenna", + "match": "Vastaavuus", + "match-all": "Kaikki (AND)", + "match-any": "Mikä tahansa (OR)", "medium": "Keskitaso", "member": "Jäsen", "members": "Jäsenet", diff --git a/public/intl/messages/fo-FO.json b/public/intl/messages/fo-FO.json index c16804397..cc7e17830 100644 --- a/public/intl/messages/fo-FO.json +++ b/public/intl/messages/fo-FO.json @@ -171,6 +171,9 @@ "manager": "Stjóri", "max": "Mest", "maximize": "Víðka", + "match": "Samsvørun", + "match-all": "Allt (AND)", + "match-any": "Nakað (OR)", "medium": "Miðal", "member": "Limur", "members": "Limir", diff --git a/public/intl/messages/fr-FR.json b/public/intl/messages/fr-FR.json index 0954df1f2..79d912d09 100644 --- a/public/intl/messages/fr-FR.json +++ b/public/intl/messages/fr-FR.json @@ -171,6 +171,9 @@ "manager": "Gestionnaire", "max": "Max", "maximize": "Développer", + "match": "Correspondance", + "match-all": "Tous (AND)", + "match-any": "N'importe lequel (OR)", "medium": "Moyen", "member": "Membre", "members": "Membres", diff --git a/public/intl/messages/ga-ES.json b/public/intl/messages/ga-ES.json index 89630c714..80ad90e21 100644 --- a/public/intl/messages/ga-ES.json +++ b/public/intl/messages/ga-ES.json @@ -171,6 +171,9 @@ "manager": "Xestor", "max": "Máx", "maximize": "Expandir", + "match": "Coincidencia", + "match-all": "Todo (AND)", + "match-any": "Calquera (OR)", "medium": "Medio", "member": "Membro", "members": "Membros", diff --git a/public/intl/messages/he-IL.json b/public/intl/messages/he-IL.json index 62c83c35b..63a5f1d4e 100644 --- a/public/intl/messages/he-IL.json +++ b/public/intl/messages/he-IL.json @@ -171,6 +171,9 @@ "manager": "מנהל", "max": "מקסימום", "maximize": "הרחב", + "match": "התאמה", + "match-all": "הכל (AND)", + "match-any": "כלשהו (OR)", "medium": "בינוני", "member": "חבר", "members": "חברים", diff --git a/public/intl/messages/hi-IN.json b/public/intl/messages/hi-IN.json index c8ac7df42..a148cff2c 100644 --- a/public/intl/messages/hi-IN.json +++ b/public/intl/messages/hi-IN.json @@ -171,6 +171,9 @@ "manager": "प्रबंधक", "max": "अधिकतम", "maximize": "विस्तार करें", + "match": "मेल", + "match-all": "सभी (AND)", + "match-any": "कोई भी (OR)", "medium": "मध्यम", "member": "सदस्य", "members": "सदस्यगण", diff --git a/public/intl/messages/hr-HR.json b/public/intl/messages/hr-HR.json index c49a9dcf3..50b5a745d 100644 --- a/public/intl/messages/hr-HR.json +++ b/public/intl/messages/hr-HR.json @@ -171,6 +171,9 @@ "manager": "Upravitelj", "max": "Maksimum", "maximize": "Proširi", + "match": "Podudaranje", + "match-all": "Sve (AND)", + "match-any": "Bilo koje (OR)", "medium": "Srednje", "member": "Član", "members": "Članovi", diff --git a/public/intl/messages/hu-HU.json b/public/intl/messages/hu-HU.json index ce071cc5f..5a72da344 100644 --- a/public/intl/messages/hu-HU.json +++ b/public/intl/messages/hu-HU.json @@ -171,6 +171,9 @@ "manager": "Menedzser", "max": "Maximum", "maximize": "Kibontás", + "match": "Egyezés", + "match-all": "Összes (AND)", + "match-any": "Bármelyik (OR)", "medium": "Közepes", "member": "Tag", "members": "Tagok", diff --git a/public/intl/messages/id-ID.json b/public/intl/messages/id-ID.json index 422bc114b..c3e14b46f 100644 --- a/public/intl/messages/id-ID.json +++ b/public/intl/messages/id-ID.json @@ -171,6 +171,9 @@ "manager": "Manajer", "max": "Maksimum", "maximize": "Perluas", + "match": "Cocok", + "match-all": "Semua (AND)", + "match-any": "Salah satu (OR)", "medium": "Sedang", "member": "Anggota", "members": "Anggota", diff --git a/public/intl/messages/it-IT.json b/public/intl/messages/it-IT.json index 00f83c304..5f1ee153e 100644 --- a/public/intl/messages/it-IT.json +++ b/public/intl/messages/it-IT.json @@ -171,6 +171,9 @@ "manager": "Gestore", "max": "Massimo", "maximize": "Espandi", + "match": "Corrispondenza", + "match-all": "Tutti (AND)", + "match-any": "Qualsiasi (OR)", "medium": "Medio", "member": "Membro", "members": "Membri", diff --git a/public/intl/messages/ja-JP.json b/public/intl/messages/ja-JP.json index 2c2347ffd..d8d9dbc49 100644 --- a/public/intl/messages/ja-JP.json +++ b/public/intl/messages/ja-JP.json @@ -171,6 +171,9 @@ "manager": "管理者", "max": "最大", "maximize": "展開", + "match": "一致", + "match-all": "すべて (AND)", + "match-any": "いずれか (OR)", "medium": "メディア", "member": "メンバー", "members": "メンバー", diff --git a/public/intl/messages/km-KH.json b/public/intl/messages/km-KH.json index a8bcb040d..0a13399d7 100644 --- a/public/intl/messages/km-KH.json +++ b/public/intl/messages/km-KH.json @@ -171,6 +171,9 @@ "manager": "អ្នកគ្រប់គ្រង", "max": "អតិបរមា", "maximize": "ពង្រីក", + "match": "ត្រូវគ្នា", + "match-all": "ទាំងអស់ (AND)", + "match-any": "ណាមួយ (OR)", "medium": "មធ្យម", "member": "សមាជិក", "members": "សមាជិក", diff --git a/public/intl/messages/ko-KR.json b/public/intl/messages/ko-KR.json index 45ce769a8..d88da6ad1 100644 --- a/public/intl/messages/ko-KR.json +++ b/public/intl/messages/ko-KR.json @@ -171,6 +171,9 @@ "manager": "관리자", "max": "최대", "maximize": "확장", + "match": "일치", + "match-all": "전체 (AND)", + "match-any": "일부 (OR)", "medium": "미디엄", "member": "멤버", "members": "멤버", diff --git a/public/intl/messages/lt-LT.json b/public/intl/messages/lt-LT.json index 9ff1d6a33..34ee0d025 100644 --- a/public/intl/messages/lt-LT.json +++ b/public/intl/messages/lt-LT.json @@ -171,6 +171,9 @@ "manager": "Vadovas", "max": "Maksimumas", "maximize": "Išplėsti", + "match": "Atitikimas", + "match-all": "Visi (AND)", + "match-any": "Bet kuris (OR)", "medium": "Vidutinis", "member": "Narys", "members": "Nariai", diff --git a/public/intl/messages/mn-MN.json b/public/intl/messages/mn-MN.json index a8e270509..100c385f5 100644 --- a/public/intl/messages/mn-MN.json +++ b/public/intl/messages/mn-MN.json @@ -171,6 +171,9 @@ "manager": "Удирдагч", "max": "Дээд", "maximize": "Өргөтгөх", + "match": "Тохирох", + "match-all": "Бүгд (AND)", + "match-any": "Ямар ч (OR)", "medium": "Дунд", "member": "Гишүүн", "members": "Гишүүд", diff --git a/public/intl/messages/ms-MY.json b/public/intl/messages/ms-MY.json index 760224217..ecc282cab 100644 --- a/public/intl/messages/ms-MY.json +++ b/public/intl/messages/ms-MY.json @@ -171,6 +171,9 @@ "manager": "Pengurus", "max": "Maks", "maximize": "Expand", + "match": "Padanan", + "match-all": "Semua (AND)", + "match-any": "Mana-mana (OR)", "medium": "Medium", "member": "Ahli", "members": "Ahli", diff --git a/public/intl/messages/my-MM.json b/public/intl/messages/my-MM.json index d31ebdb25..88e966ac4 100644 --- a/public/intl/messages/my-MM.json +++ b/public/intl/messages/my-MM.json @@ -171,6 +171,9 @@ "manager": "မန်နေဂျာ", "max": "အများဆုံး", "maximize": "Expand", + "match": "ကိုက်ညီ", + "match-all": "အားလုံး (AND)", + "match-any": "တစ်ခုခု (OR)", "medium": "မီဒီယမ်", "member": "အဖွဲ့ဝင်", "members": "အဖွဲ့ဝင်များ", diff --git a/public/intl/messages/nb-NO.json b/public/intl/messages/nb-NO.json index c0007cd3d..1296ee814 100644 --- a/public/intl/messages/nb-NO.json +++ b/public/intl/messages/nb-NO.json @@ -171,6 +171,9 @@ "manager": "Administrator", "max": "Maks", "maximize": "Utvid", + "match": "Samsvar", + "match-all": "Alle (AND)", + "match-any": "Enhver (OR)", "medium": "Medium", "member": "Bruker", "members": "Brukere", diff --git a/public/intl/messages/nl-NL.json b/public/intl/messages/nl-NL.json index cf56e8b8d..69818e3a8 100644 --- a/public/intl/messages/nl-NL.json +++ b/public/intl/messages/nl-NL.json @@ -171,6 +171,9 @@ "manager": "Beheerder", "max": "Max", "maximize": "Uitvouwen", + "match": "Overeenkomst", + "match-all": "Alle (AND)", + "match-any": "Elk (OR)", "medium": "Medium", "member": "Gebruiker", "members": "Gebruikers", diff --git a/public/intl/messages/pl-PL.json b/public/intl/messages/pl-PL.json index 1f486cb55..dad1f2327 100644 --- a/public/intl/messages/pl-PL.json +++ b/public/intl/messages/pl-PL.json @@ -171,6 +171,9 @@ "manager": "Menedżer", "max": "Maks", "maximize": "Rozwiń", + "match": "Dopasowanie", + "match-all": "Wszystkie (AND)", + "match-any": "Dowolny (OR)", "medium": "Medium", "member": "Członek", "members": "Członkowie", diff --git a/public/intl/messages/pt-BR.json b/public/intl/messages/pt-BR.json index 282981df4..8ccfa3991 100644 --- a/public/intl/messages/pt-BR.json +++ b/public/intl/messages/pt-BR.json @@ -171,6 +171,9 @@ "manager": "Gerente", "max": "Máximo", "maximize": "Expandir", + "match": "Correspondência", + "match-all": "Todos (AND)", + "match-any": "Qualquer (OR)", "medium": "Médio", "member": "Membro", "members": "Membros", diff --git a/public/intl/messages/pt-PT.json b/public/intl/messages/pt-PT.json index 907d8e4f2..4b52892c3 100644 --- a/public/intl/messages/pt-PT.json +++ b/public/intl/messages/pt-PT.json @@ -171,6 +171,9 @@ "manager": "Gestor", "max": "Máximo", "maximize": "Expandir", + "match": "Correspondência", + "match-all": "Todos (AND)", + "match-any": "Qualquer (OR)", "medium": "Médio", "member": "Membro", "members": "Membros", diff --git a/public/intl/messages/ro-RO.json b/public/intl/messages/ro-RO.json index b81556524..86c804777 100644 --- a/public/intl/messages/ro-RO.json +++ b/public/intl/messages/ro-RO.json @@ -171,6 +171,9 @@ "manager": "Manager", "max": "Max", "maximize": "Extinde", + "match": "Potrivire", + "match-all": "Toate (AND)", + "match-any": "Oricare (OR)", "medium": "Mediu", "member": "Membru", "members": "Membri", diff --git a/public/intl/messages/ru-RU.json b/public/intl/messages/ru-RU.json index 10096a5dc..8296e160f 100644 --- a/public/intl/messages/ru-RU.json +++ b/public/intl/messages/ru-RU.json @@ -171,6 +171,9 @@ "manager": "Менеджер", "max": "Максимум", "maximize": "Развернуть", + "match": "Соответствие", + "match-all": "Все (AND)", + "match-any": "Любой (OR)", "medium": "Средний", "member": "Участник", "members": "Участники", diff --git a/public/intl/messages/si-LK.json b/public/intl/messages/si-LK.json index cb2b6163e..5aa2bd89a 100644 --- a/public/intl/messages/si-LK.json +++ b/public/intl/messages/si-LK.json @@ -171,6 +171,9 @@ "manager": "කළමනාකරු", "max": "උපරිම", "maximize": "Expand", + "match": "ගැළපීම", + "match-all": "සියල්ල (AND)", + "match-any": "ඕනෑම (OR)", "medium": "මාධ්‍යය", "member": "සාමාජිකයා", "members": "සාමාජිකයින්", diff --git a/public/intl/messages/sk-SK.json b/public/intl/messages/sk-SK.json index f3424a3ee..f51951f93 100644 --- a/public/intl/messages/sk-SK.json +++ b/public/intl/messages/sk-SK.json @@ -171,6 +171,9 @@ "manager": "Manažér", "max": "Maximum", "maximize": "Rozbaliť", + "match": "Zhoda", + "match-all": "Všetky (AND)", + "match-any": "Akýkoľvek (OR)", "medium": "Stredný", "member": "Člen", "members": "Členovia", diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index 34d9d731f..cea57d48e 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -171,6 +171,9 @@ "manager": "Upravitelj", "max": "Največ", "maximize": "Povečaj", + "match": "Ujemanje", + "match-all": "Vse (AND)", + "match-any": "Katero koli (OR)", "medium": "Medij", "member": "Član", "members": "Člani", diff --git a/public/intl/messages/sv-SE.json b/public/intl/messages/sv-SE.json index a39bbeb0e..e8f842e3e 100644 --- a/public/intl/messages/sv-SE.json +++ b/public/intl/messages/sv-SE.json @@ -171,6 +171,9 @@ "manager": "Ansvarig", "max": "Max", "maximize": "Expandera", + "match": "Matchning", + "match-all": "Alla (AND)", + "match-any": "Vilken som helst (OR)", "medium": "Medium", "member": "Medlem", "members": "Medlemmar", diff --git a/public/intl/messages/ta-IN.json b/public/intl/messages/ta-IN.json index 9d7fe5b16..6cf4388fa 100644 --- a/public/intl/messages/ta-IN.json +++ b/public/intl/messages/ta-IN.json @@ -171,6 +171,9 @@ "manager": "மேலாளர்", "max": "அதிகபட்சம்", "maximize": "Expand", + "match": "பொருத்தம்", + "match-all": "அனைத்தும் (AND)", + "match-any": "எதுவும் (OR)", "medium": "ஊடகம்", "member": "உறுப்பினர்", "members": "உறுப்பினர்கள்", diff --git a/public/intl/messages/th-TH.json b/public/intl/messages/th-TH.json index 5af2e6713..168cc057a 100644 --- a/public/intl/messages/th-TH.json +++ b/public/intl/messages/th-TH.json @@ -171,6 +171,9 @@ "manager": "ผู้จัดการ", "max": "สูงสุด", "maximize": "Expand", + "match": "จับคู่", + "match-all": "ทั้งหมด (AND)", + "match-any": "ใดๆ (OR)", "medium": "สื่อ", "member": "สมาชิก", "members": "สมาชิก", diff --git a/public/intl/messages/tr-TR.json b/public/intl/messages/tr-TR.json index 667da45bf..139aee6af 100644 --- a/public/intl/messages/tr-TR.json +++ b/public/intl/messages/tr-TR.json @@ -171,6 +171,9 @@ "manager": "Yönetici", "max": "Maks", "maximize": "Genişlet", + "match": "Eşleşme", + "match-all": "Tümü (AND)", + "match-any": "Herhangi (OR)", "medium": "Orta", "member": "Üye", "members": "Üyeler", diff --git a/public/intl/messages/uk-UA.json b/public/intl/messages/uk-UA.json index 5d83a9aa2..5f78c2bfe 100644 --- a/public/intl/messages/uk-UA.json +++ b/public/intl/messages/uk-UA.json @@ -171,6 +171,9 @@ "manager": "Менеджер", "max": "Макс.", "maximize": "Розгорнути", + "match": "Відповідність", + "match-all": "Усі (AND)", + "match-any": "Будь-який (OR)", "medium": "Середній", "member": "Учасник", "members": "Учасники", diff --git a/public/intl/messages/ur-PK.json b/public/intl/messages/ur-PK.json index 0e03241fc..a1d07dbe2 100644 --- a/public/intl/messages/ur-PK.json +++ b/public/intl/messages/ur-PK.json @@ -171,6 +171,9 @@ "manager": "منتظم", "max": "زیادہ سے زیادہ", "maximize": "Expand", + "match": "مطابقت", + "match-all": "سب (AND)", + "match-any": "کوئی بھی (OR)", "medium": "میڈیم", "member": "رکن", "members": "اراکین", diff --git a/public/intl/messages/uz-UZ.json b/public/intl/messages/uz-UZ.json index b2b60d5b7..de0ad0085 100644 --- a/public/intl/messages/uz-UZ.json +++ b/public/intl/messages/uz-UZ.json @@ -171,6 +171,9 @@ "manager": "Menejer", "max": "Maksimal", "maximize": "Kattalashtirish", + "match": "Moslik", + "match-all": "Barchasi (AND)", + "match-any": "Istalgan (OR)", "medium": "Vosita", "member": "A'zo", "members": "A'zolar", diff --git a/public/intl/messages/vi-VN.json b/public/intl/messages/vi-VN.json index eed6aa8dc..2b9514fc4 100644 --- a/public/intl/messages/vi-VN.json +++ b/public/intl/messages/vi-VN.json @@ -171,6 +171,9 @@ "manager": "Quản lý", "max": "Tối đa", "maximize": "Phóng to", + "match": "Khớp", + "match-all": "Tất cả (AND)", + "match-any": "Bất kỳ (OR)", "medium": "Phương tiện", "member": "Thành viên", "members": "Các thành viên", diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index 8f1469a3a..4d65d885f 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -171,6 +171,9 @@ "manager": "管理者", "max": "最大", "maximize": "展开", + "match": "匹配", + "match-all": "全部 (AND)", + "match-any": "任意 (OR)", "medium": "中等", "member": "成员", "members": "成员", diff --git a/public/intl/messages/zh-TW.json b/public/intl/messages/zh-TW.json index 57cd293c1..05d304f4b 100644 --- a/public/intl/messages/zh-TW.json +++ b/public/intl/messages/zh-TW.json @@ -171,6 +171,9 @@ "manager": "管理者", "max": "最大值", "maximize": "Expand", + "match": "符合", + "match-all": "全部 (AND)", + "match-any": "任意 (OR)", "medium": "媒介", "member": "成員", "members": "成員", diff --git a/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx b/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx index dbce37df8..8ad13549d 100644 --- a/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx @@ -10,6 +10,7 @@ import { Loading, TextField, } from '@umami/react-zen'; +import { useEffect, useState } from 'react'; import { useMessages, useUpdateQuery, useWebsiteCohortQuery } from '@/components/hooks'; import { ActionSelect } from '@/components/input/ActionSelect'; import { DateFilter } from '@/components/input/DateFilter'; @@ -32,6 +33,11 @@ export function CohortEditForm({ }) { const { data } = useWebsiteCohortQuery(websiteId, cohortId); const { t, labels, messages, getErrorMessage } = useMessages(); + const [currentMatch, setCurrentMatch] = useState('all'); + + useEffect(() => { + setCurrentMatch((data?.parameters as any)?.match || 'all'); + }, [data]); const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery( `/websites/${websiteId}/segments${cohortId ? `/${cohortId}` : ''}`, @@ -41,14 +47,23 @@ export function CohortEditForm({ ); const handleSubmit = async (formData: any) => { - await mutateAsync(formData, { - onSuccess: async () => { - toast(t(messages.saved)); - touch('cohorts'); - onSave?.(); - onClose?.(); + await mutateAsync( + { + ...formData, + parameters: { + ...formData.parameters, + match: currentMatch !== 'all' ? currentMatch : undefined, + }, }, - }); + { + onSuccess: async () => { + toast(t(messages.saved)); + touch('cohorts'); + onSave?.(); + onClose?.(); + }, + }, + ); }; if (cohortId && !data) { @@ -105,7 +120,12 @@ export function CohortEditForm({ - + diff --git a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx index 5798351ac..553c0c9b6 100644 --- a/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/segments/SegmentEditForm.tsx @@ -8,6 +8,7 @@ import { Loading, TextField, } from '@umami/react-zen'; +import { useEffect, useState } from 'react'; import { useMessages, useUpdateQuery, useWebsiteSegmentQuery } from '@/components/hooks'; import { FieldFilters } from '@/components/input/FieldFilters'; @@ -28,6 +29,11 @@ export function SegmentEditForm({ }) { const { data } = useWebsiteSegmentQuery(websiteId, segmentId); const { t, labels, messages, getErrorMessage } = useMessages(); + const [currentMatch, setCurrentMatch] = useState('all'); + + useEffect(() => { + setCurrentMatch((data?.parameters as any)?.match || 'all'); + }, [data]); const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery( `/websites/${websiteId}/segments${segmentId ? `/${segmentId}` : ''}`, @@ -37,14 +43,23 @@ export function SegmentEditForm({ ); const handleSubmit = async (formData: any) => { - await mutateAsync(formData, { - onSuccess: async () => { - toast(t(messages.saved)); - touch('segments'); - onSave?.(); - onClose?.(); + await mutateAsync( + { + ...formData, + parameters: { + ...formData.parameters, + match: currentMatch !== 'all' ? currentMatch : undefined, + }, }, - }); + { + onSuccess: async () => { + toast(t(messages.saved)); + touch('segments'); + onSave?.(); + onClose?.(); + }, + }, + ); }; if (segmentId && !data) { @@ -64,7 +79,11 @@ export function SegmentEditForm({ <> - + )} diff --git a/src/components/hooks/useFilterParameters.ts b/src/components/hooks/useFilterParameters.ts index b4b9391b9..3579bef95 100644 --- a/src/components/hooks/useFilterParameters.ts +++ b/src/components/hooks/useFilterParameters.ts @@ -21,6 +21,7 @@ export function useFilterParameters() { segment: query.segment, cohort: query.cohort, excludeBounce: query.excludeBounce, + match: query.match, page: query.page, pageSize: query.pageSize, }; diff --git a/src/components/input/FieldFilters.tsx b/src/components/input/FieldFilters.tsx index 0d4aaf035..ec8d63241 100644 --- a/src/components/input/FieldFilters.tsx +++ b/src/components/input/FieldFilters.tsx @@ -3,6 +3,7 @@ import { Column, Grid, Icon, + Label, List, ListItem, ListSection, @@ -12,6 +13,7 @@ import { MenuTrigger, Popover, Row, + Select, } from '@umami/react-zen'; import { endOfDay, subMonths } from 'date-fns'; import type { Key } from 'react'; @@ -24,11 +26,20 @@ export interface FieldFiltersProps { websiteId: string; value?: { name: string; operator: string; value: string }[]; exclude?: string[]; + match?: string; onChange?: (data: any) => void; + onMatchChange?: (match: string) => void; } -export function FieldFilters({ websiteId, value, exclude = [], onChange }: FieldFiltersProps) { - const { t, messages } = useMessages(); +export function FieldFilters({ + websiteId, + value, + exclude = [], + match = 'all', + onChange, + onMatchChange, +}: FieldFiltersProps) { + const { t, labels, messages } = useMessages(); const { fields, groupLabels } = useFields(); const startDate = subMonths(endOfDay(new Date()), 6); const endDate = endOfDay(new Date()); @@ -126,6 +137,17 @@ export function FieldFilters({ websiteId, value, exclude = [], onChange }: Field + {onMatchChange && ( + + + + + + + )} {value.map((filter, index) => { return ( void; + onChange?: (params: { + filters: any[]; + segment?: string; + cohort?: string; + match?: string; + }) => void; onClose?: () => void; } export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormProps) { const { - query: { segment, cohort }, + query: { segment, cohort, match }, pathname, } = useNavigation(); const { filters } = useFilters(); @@ -20,6 +25,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP const [currentFilters, setCurrentFilters] = useState(filters); const [currentSegment, setCurrentSegment] = useState(segment); const [currentCohort, setCurrentCohort] = useState(cohort); + const [currentMatch, setCurrentMatch] = useState(match || 'all'); const { isMobile } = useMobile(); const excludeFilters = pathname.includes('/pixels') || pathname.includes('/links'); const excludeEvent = !pathname.endsWith('/events'); @@ -28,6 +34,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP setCurrentFilters([]); setCurrentSegment(undefined); setCurrentCohort(undefined); + setCurrentMatch('all'); }; const handleSave = () => { @@ -35,6 +42,7 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP filters: currentFilters.filter(f => f.value), segment: currentSegment, cohort: currentCohort, + match: currentMatch !== 'all' ? currentMatch : undefined, }); onClose?.(); }; @@ -61,7 +69,9 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP {t(labels.reset)} - diff --git a/src/components/input/WebsiteFilterButton.tsx b/src/components/input/WebsiteFilterButton.tsx index c558374ec..e2484727a 100644 --- a/src/components/input/WebsiteFilterButton.tsx +++ b/src/components/input/WebsiteFilterButton.tsx @@ -19,13 +19,14 @@ export function WebsiteFilterButton({ const isOverview = /^\/teams\/[^/]+\/websites\/[^/]+$/.test(pathname) || /^\/share\/[^/]+$/.test(pathname); - const handleChange = ({ filters, segment, cohort }: any) => { + const handleChange = ({ filters, segment, cohort, match }: any) => { const params = filtersArrayToObject(filters); const url = updateParams({ ...params, segment, cohort, + match, excludeBounce: excludeBounce ? 'true' : undefined, }); diff --git a/src/components/messages.ts b/src/components/messages.ts index a0c6f9172..f3ee22834 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -305,6 +305,9 @@ export const labels: Record = { other: 'label.other', boards: 'label.boards', apply: 'label.apply', + match: 'label.match', + matchAll: 'label.match-all', + matchAny: 'label.match-any', link: 'label.link', links: 'label.links', pixel: 'label.pixel', diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index cbe5022d1..b6a655d47 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -99,32 +99,44 @@ function mapFilter( } function getFilterQuery(filters: Record, options: QueryOptions = {}) { - const query = filtersObjectToArray(filters, options).reduce( - (arr, { name, column, operator, paramName }) => { - const isCohort = options?.isCohort; + const { isCohort, cohortMatch, cohortActionName } = options; + const isOr = isCohort ? cohortMatch === 'any' : filters.match === 'any'; + const orClauses: string[] = []; + const andClauses: string[] = []; - if (isCohort) { - column = FILTER_COLUMNS[name.slice('cohort_'.length)]; + filtersObjectToArray(filters, options).forEach(({ name, column, operator, paramName }) => { + if (isCohort) { + column = FILTER_COLUMNS[name.slice('cohort_'.length)]; + } + + if (column) { + const isAlwaysAnd = name === 'eventType' || (isCohort && name === cohortActionName); + + if (isAlwaysAnd) { + andClauses.push( + `and ${mapFilter(column, operator, name, name === 'eventType' ? 'UInt32' : 'String', paramName)}`, + ); + } else if (isOr) { + orClauses.push(mapFilter(column, operator, name, 'String', paramName)); + } else { + andClauses.push(`and ${mapFilter(column, operator, name, 'String', paramName)}`); } - if (column) { - if (name === 'eventType') { - arr.push(`and ${mapFilter(column, operator, name, 'UInt32', paramName)}`); - } else { - arr.push(`and ${mapFilter(column, operator, name, 'String', paramName)}`); - } - - if (name === 'referrer') { - arr.push(`and referrer_domain != hostname`); - } + if (name === 'referrer') { + andClauses.push(`and referrer_domain != hostname`); } + } + }); - return arr; - }, - [], - ); + const parts: string[] = []; - return query.join('\n'); + if (orClauses.length > 0) { + parts.push(`and (\n ${orClauses.join('\n or ')}\n)`); + } + + parts.push(...andClauses); + + return parts.join('\n'); } function getCohortQuery(filters: Record) { @@ -132,7 +144,10 @@ function getCohortQuery(filters: Record) { return ''; } - const filterQuery = getFilterQuery(filters, { isCohort: true }); + const cohortMatch = filters.cohort_match; + const cohortActionName = filters.cohort_actionName; + + const filterQuery = getFilterQuery(filters, { isCohort: true, cohortMatch, cohortActionName }); return `join ( select distinct session_id @@ -267,7 +282,7 @@ async function rawQuery( output_format_json_quote_64bit_integers: 0, }, }); - + console.log(query, params); return (await resultSet.json()) as T; } diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index f10cc041f..19fd421ec 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -106,30 +106,47 @@ function mapFilter( } function getFilterQuery(filters: Record, options: QueryOptions = {}): string { - const query = filtersObjectToArray(filters, options).reduce( - (arr, { name, column, operator, prefix = '', paramName }) => { - const isCohort = options?.isCohort; + const { isCohort, cohortMatch, cohortActionName } = options; + const isOr = isCohort ? cohortMatch === 'any' : filters.match === 'any'; + const orClauses: string[] = []; + const andClauses: string[] = []; + filtersObjectToArray(filters, options).forEach( + ({ name, column, operator, prefix = '', paramName }) => { if (isCohort) { column = FILTER_COLUMNS[name.slice('cohort_'.length)]; } if (column) { - arr.push(`and ${mapFilter(`${prefix}${column}`, operator, name, '', paramName)}`); + const clause = mapFilter(`${prefix}${column}`, operator, name, '', paramName); + const isAlwaysAnd = name === 'eventType' || (isCohort && name === cohortActionName); + + if (isAlwaysAnd) { + andClauses.push(`and ${clause}`); + } else if (isOr) { + orClauses.push(clause); + } else { + andClauses.push(`and ${clause}`); + } if (name === 'referrer') { - arr.push( + andClauses.push( `and (website_event.referrer_domain != regexp_replace(website_event.hostname, '^www.', '') or website_event.referrer_domain is null)`, ); } } - - return arr; }, - [], ); - return query.join('\n'); + const parts: string[] = []; + + if (orClauses.length > 0) { + parts.push(`and (\n ${orClauses.join('\n or ')}\n)`); + } + + parts.push(...andClauses); + + return parts.join('\n'); } function getCohortQuery(filters: QueryFilters = {}) { @@ -137,7 +154,10 @@ function getCohortQuery(filters: QueryFilters = {}) { return ''; } - const filterQuery = getFilterQuery(filters, { isCohort: true }); + const cohortMatch = (filters as any).cohort_match; + const cohortActionName = (filters as any).cohort_actionName; + + const filterQuery = getFilterQuery(filters, { isCohort: true, cohortMatch, cohortActionName }); return `join (select distinct website_event.session_id diff --git a/src/lib/request.ts b/src/lib/request.ts index 767288feb..69f6eb1d7 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -115,6 +115,8 @@ export async function getQueryFilters( const dateRange = getRequestDateRange(params); const filters = getRequestFilters(params); + let match = params?.match; + if (websiteId) { await setWebsiteDate(websiteId, dateRange); @@ -123,6 +125,10 @@ export async function getQueryFilters( ?.parameters as Record; Object.assign(filters, filtersArrayToObject(segmentParams.filters)); + + if (segmentParams.match) { + match = segmentParams.match; + } } if (params.cohort) { @@ -146,6 +152,10 @@ export async function getQueryFilters( ...filtersArrayToObject(cohortFilters), cohort_startDate: startDate, cohort_endDate: endDate, + ...(cohortParams.match && { + cohort_match: cohortParams.match, + cohort_actionName: `cohort_${cohortParams.action.type}`, + }), }); } @@ -157,6 +167,7 @@ export async function getQueryFilters( return { ...dateRange, ...filters, + match, page: params?.page, pageSize: params?.pageSize ? params?.pageSize || DEFAULT_PAGE_SIZE : undefined, orderBy: params?.orderBy, diff --git a/src/lib/schema.ts b/src/lib/schema.ts index 41cfc70f9..1755d4fa1 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -67,6 +67,7 @@ export const filterParams = { cohort: z.uuid().optional(), eventType: z.coerce.number().int().positive().optional(), excludeBounce: z.string().optional(), + match: z.enum(['all', 'any']).optional(), }; export const searchParams = { @@ -295,6 +296,7 @@ export const segmentParamSchema = z.object({ }), ) .optional(), + match: z.enum(['all', 'any']).optional(), dateRange: z.string().optional(), action: z .object({ diff --git a/src/lib/types.ts b/src/lib/types.ts index e722195aa..caa3e1e73 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -53,6 +53,8 @@ export interface QueryOptions { limit?: number; prefix?: string; isCohort?: boolean; + cohortMatch?: string; + cohortActionName?: string; } export interface QueryFilters @@ -93,6 +95,7 @@ export interface FilterParams { cohort?: string; compare?: string; excludeBounce?: boolean; + match?: 'all' | 'any'; } export interface SortParams {