@posthog/core 1.27.9 → 1.28.1

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 (55) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/logs/index.d.ts +94 -4
  4. package/dist/logs/index.d.ts.map +1 -1
  5. package/dist/logs/index.js +149 -4
  6. package/dist/logs/index.mjs +150 -5
  7. package/dist/logs/logs-utils.d.ts +2 -1
  8. package/dist/logs/logs-utils.d.ts.map +1 -1
  9. package/dist/logs/types.d.ts +140 -8
  10. package/dist/logs/types.d.ts.map +1 -1
  11. package/dist/posthog-core-stateless.d.ts +34 -0
  12. package/dist/posthog-core-stateless.d.ts.map +1 -1
  13. package/dist/posthog-core-stateless.js +46 -0
  14. package/dist/posthog-core-stateless.mjs +46 -0
  15. package/dist/posthog-core.d.ts.map +1 -1
  16. package/dist/posthog-core.js +2 -0
  17. package/dist/posthog-core.mjs +2 -0
  18. package/dist/surveys/events.d.ts +22 -0
  19. package/dist/surveys/events.d.ts.map +1 -0
  20. package/dist/surveys/events.js +95 -0
  21. package/dist/surveys/events.mjs +43 -0
  22. package/dist/surveys/index.d.ts +4 -0
  23. package/dist/surveys/index.d.ts.map +1 -0
  24. package/dist/surveys/index.js +83 -0
  25. package/dist/surveys/index.mjs +4 -0
  26. package/dist/surveys/translations.d.ts +38 -0
  27. package/dist/surveys/translations.d.ts.map +1 -0
  28. package/dist/surveys/translations.js +207 -0
  29. package/dist/surveys/translations.mjs +158 -0
  30. package/dist/testing/test-utils.d.ts.map +1 -1
  31. package/dist/testing/test-utils.js +1 -0
  32. package/dist/testing/test-utils.mjs +1 -0
  33. package/dist/types.d.ts +31 -2
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/utils/logger.d.ts +1 -1
  36. package/dist/utils/logger.d.ts.map +1 -1
  37. package/dist/utils/logger.js +3 -0
  38. package/dist/utils/logger.mjs +3 -0
  39. package/package.json +26 -2
  40. package/src/index.ts +12 -1
  41. package/src/logs/index.spec.ts +891 -17
  42. package/src/logs/index.ts +341 -11
  43. package/src/logs/logs-utils.spec.ts +2 -1
  44. package/src/logs/logs-utils.ts +1 -1
  45. package/src/logs/types.ts +150 -25
  46. package/src/posthog-core-stateless.ts +80 -0
  47. package/src/posthog-core.ts +6 -0
  48. package/src/surveys/events.spec.ts +52 -0
  49. package/src/surveys/events.ts +80 -0
  50. package/src/surveys/index.ts +18 -0
  51. package/src/surveys/translations.spec.ts +205 -0
  52. package/src/surveys/translations.ts +244 -0
  53. package/src/testing/test-utils.ts +1 -0
  54. package/src/types.ts +38 -2
  55. package/src/utils/logger.ts +6 -2
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ getSurveyInteractionProperty: ()=>external_events_js_namespaceObject.getSurveyInteractionProperty,
28
+ getSurveyOldResponseKey: ()=>external_events_js_namespaceObject.getSurveyOldResponseKey,
29
+ getBaseLanguage: ()=>external_translations_js_namespaceObject.getBaseLanguage,
30
+ getSurveyResponseValue: ()=>external_events_js_namespaceObject.getSurveyResponseValue,
31
+ SURVEY_LANGUAGE_PROPERTY: ()=>external_events_js_namespaceObject.SURVEY_LANGUAGE_PROPERTY,
32
+ detectSurveyLanguage: ()=>external_translations_js_namespaceObject.detectSurveyLanguage,
33
+ applySurveyTranslation: ()=>external_translations_js_namespaceObject.applySurveyTranslation,
34
+ getValidationError: ()=>external_validation_js_namespaceObject.getValidationError,
35
+ getLanguageFromStoredPersonProperties: ()=>external_translations_js_namespaceObject.getLanguageFromStoredPersonProperties,
36
+ buildSurveyResponseProperties: ()=>external_events_js_namespaceObject.buildSurveyResponseProperties,
37
+ getRequirementsHint: ()=>external_validation_js_namespaceObject.getRequirementsHint,
38
+ findBestTranslationMatch: ()=>external_translations_js_namespaceObject.findBestTranslationMatch,
39
+ normalizeLanguageCode: ()=>external_translations_js_namespaceObject.normalizeLanguageCode,
40
+ getSurveyResponseKey: ()=>external_events_js_namespaceObject.getSurveyResponseKey,
41
+ getLengthFromRules: ()=>external_validation_js_namespaceObject.getLengthFromRules,
42
+ surveyHasResponses: ()=>external_events_js_namespaceObject.surveyHasResponses
43
+ });
44
+ const external_validation_js_namespaceObject = require("./validation.js");
45
+ const external_events_js_namespaceObject = require("./events.js");
46
+ const external_translations_js_namespaceObject = require("./translations.js");
47
+ exports.SURVEY_LANGUAGE_PROPERTY = __webpack_exports__.SURVEY_LANGUAGE_PROPERTY;
48
+ exports.applySurveyTranslation = __webpack_exports__.applySurveyTranslation;
49
+ exports.buildSurveyResponseProperties = __webpack_exports__.buildSurveyResponseProperties;
50
+ exports.detectSurveyLanguage = __webpack_exports__.detectSurveyLanguage;
51
+ exports.findBestTranslationMatch = __webpack_exports__.findBestTranslationMatch;
52
+ exports.getBaseLanguage = __webpack_exports__.getBaseLanguage;
53
+ exports.getLanguageFromStoredPersonProperties = __webpack_exports__.getLanguageFromStoredPersonProperties;
54
+ exports.getLengthFromRules = __webpack_exports__.getLengthFromRules;
55
+ exports.getRequirementsHint = __webpack_exports__.getRequirementsHint;
56
+ exports.getSurveyInteractionProperty = __webpack_exports__.getSurveyInteractionProperty;
57
+ exports.getSurveyOldResponseKey = __webpack_exports__.getSurveyOldResponseKey;
58
+ exports.getSurveyResponseKey = __webpack_exports__.getSurveyResponseKey;
59
+ exports.getSurveyResponseValue = __webpack_exports__.getSurveyResponseValue;
60
+ exports.getValidationError = __webpack_exports__.getValidationError;
61
+ exports.normalizeLanguageCode = __webpack_exports__.normalizeLanguageCode;
62
+ exports.surveyHasResponses = __webpack_exports__.surveyHasResponses;
63
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
64
+ "SURVEY_LANGUAGE_PROPERTY",
65
+ "applySurveyTranslation",
66
+ "buildSurveyResponseProperties",
67
+ "detectSurveyLanguage",
68
+ "findBestTranslationMatch",
69
+ "getBaseLanguage",
70
+ "getLanguageFromStoredPersonProperties",
71
+ "getLengthFromRules",
72
+ "getRequirementsHint",
73
+ "getSurveyInteractionProperty",
74
+ "getSurveyOldResponseKey",
75
+ "getSurveyResponseKey",
76
+ "getSurveyResponseValue",
77
+ "getValidationError",
78
+ "normalizeLanguageCode",
79
+ "surveyHasResponses"
80
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
81
+ Object.defineProperty(exports, '__esModule', {
82
+ value: true
83
+ });
@@ -0,0 +1,4 @@
1
+ import { getLengthFromRules, getRequirementsHint, getValidationError } from "./validation.mjs";
2
+ import { SURVEY_LANGUAGE_PROPERTY, buildSurveyResponseProperties, getSurveyInteractionProperty, getSurveyOldResponseKey, getSurveyResponseKey, getSurveyResponseValue, surveyHasResponses } from "./events.mjs";
3
+ import { applySurveyTranslation, detectSurveyLanguage, findBestTranslationMatch, getBaseLanguage, getLanguageFromStoredPersonProperties, normalizeLanguageCode } from "./translations.mjs";
4
+ export { SURVEY_LANGUAGE_PROPERTY, applySurveyTranslation, buildSurveyResponseProperties, detectSurveyLanguage, findBestTranslationMatch, getBaseLanguage, getLanguageFromStoredPersonProperties, getLengthFromRules, getRequirementsHint, getSurveyInteractionProperty, getSurveyOldResponseKey, getSurveyResponseKey, getSurveyResponseValue, getValidationError, normalizeLanguageCode, surveyHasResponses };
@@ -0,0 +1,38 @@
1
+ import { SurveyQuestionTranslation, SurveyTranslation } from '../types';
2
+ export type DetectSurveyLanguageOptions = {
3
+ overrideLanguage?: unknown;
4
+ storedPersonProperties?: unknown;
5
+ locale?: unknown;
6
+ };
7
+ export declare function getLanguageFromStoredPersonProperties(storedPersonProperties: unknown): string | null;
8
+ export declare function detectSurveyLanguage({ overrideLanguage, storedPersonProperties, locale, }: DetectSurveyLanguageOptions): string | null;
9
+ export declare function normalizeLanguageCode(languageCode: string): string;
10
+ export declare function getBaseLanguage(languageCode: string): string;
11
+ export declare function findBestTranslationMatch(translations: Record<string, unknown> | undefined, targetLanguage: string): string | null;
12
+ type TranslatableSurveyAppearance = {
13
+ thankYouMessageHeader?: string;
14
+ thankYouMessageDescription?: string | null;
15
+ thankYouMessageCloseButtonText?: string;
16
+ };
17
+ type TranslatableSurveyQuestion = {
18
+ question: string;
19
+ description?: string | null;
20
+ buttonText?: string;
21
+ link?: string | null;
22
+ lowerBoundLabel?: string;
23
+ upperBoundLabel?: string;
24
+ choices?: string[];
25
+ translations?: Record<string, SurveyQuestionTranslation>;
26
+ };
27
+ type TranslatableSurvey<TQuestion extends TranslatableSurveyQuestion = TranslatableSurveyQuestion> = {
28
+ name: string;
29
+ translations?: Record<string, SurveyTranslation>;
30
+ appearance?: TranslatableSurveyAppearance | null;
31
+ questions: TQuestion[];
32
+ };
33
+ export declare function applySurveyTranslation<TQuestion extends TranslatableSurveyQuestion, TSurvey extends TranslatableSurvey<TQuestion>>(survey: TSurvey, targetLanguage: string): {
34
+ survey: TSurvey;
35
+ matchedKey: string | null;
36
+ };
37
+ export {};
38
+ //# sourceMappingURL=translations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../src/surveys/translations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAKvE,MAAM,MAAM,2BAA2B,GAAG;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAMD,wBAAgB,qCAAqC,CAAC,sBAAsB,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAUpG;AAED,wBAAgB,oBAAoB,CAAC,EACnC,gBAAgB,EAChB,sBAAsB,EACtB,MAAM,GACP,EAAE,2BAA2B,GAAG,MAAM,GAAG,IAAI,CAqB7C;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACjD,cAAc,EAAE,MAAM,GACrB,MAAM,GAAG,IAAI,CAuBf;AAgBD,KAAK,4BAA4B,GAAG;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1C,8BAA8B,CAAC,EAAE,MAAM,CAAA;CACxC,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAA;CACzD,CAAA;AAED,KAAK,kBAAkB,CAAC,SAAS,SAAS,0BAA0B,GAAG,0BAA0B,IAAI;IACnG,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAChD,UAAU,CAAC,EAAE,4BAA4B,GAAG,IAAI,CAAA;IAChD,SAAS,EAAE,SAAS,EAAE,CAAA;CACvB,CAAA;AA0DD,wBAAgB,sBAAsB,CACpC,SAAS,SAAS,0BAA0B,EAC5C,OAAO,SAAS,kBAAkB,CAAC,SAAS,CAAC,EAC7C,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAwDzF"}
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ normalizeLanguageCode: ()=>normalizeLanguageCode,
28
+ getBaseLanguage: ()=>getBaseLanguage,
29
+ detectSurveyLanguage: ()=>detectSurveyLanguage,
30
+ applySurveyTranslation: ()=>applySurveyTranslation,
31
+ findBestTranslationMatch: ()=>findBestTranslationMatch,
32
+ getLanguageFromStoredPersonProperties: ()=>getLanguageFromStoredPersonProperties
33
+ });
34
+ const index_js_namespaceObject = require("../utils/index.js");
35
+ const logger = (0, index_js_namespaceObject.createLogger)('[SurveyTranslations]');
36
+ function getTrimmedLanguage(value) {
37
+ return 'string' == typeof value && value.trim() ? value.trim() : null;
38
+ }
39
+ function getLanguageFromStoredPersonProperties(storedPersonProperties) {
40
+ if (!storedPersonProperties || 'object' != typeof storedPersonProperties || !('language' in storedPersonProperties)) return null;
41
+ return getTrimmedLanguage(storedPersonProperties.language);
42
+ }
43
+ function detectSurveyLanguage({ overrideLanguage, storedPersonProperties, locale }) {
44
+ const explicitLanguage = getTrimmedLanguage(overrideLanguage);
45
+ if (explicitLanguage) {
46
+ logger.info(`Using override display language: ${explicitLanguage}`);
47
+ return explicitLanguage;
48
+ }
49
+ const personLanguage = getLanguageFromStoredPersonProperties(storedPersonProperties);
50
+ if (personLanguage) {
51
+ logger.info(`Using person property language: ${personLanguage}`);
52
+ return personLanguage;
53
+ }
54
+ const detectedLocale = getTrimmedLanguage(locale);
55
+ if (detectedLocale) {
56
+ logger.info(`Using detected locale: ${detectedLocale}`);
57
+ return detectedLocale;
58
+ }
59
+ logger.info('No user language detected');
60
+ return null;
61
+ }
62
+ function normalizeLanguageCode(languageCode) {
63
+ return languageCode.toLowerCase();
64
+ }
65
+ function getBaseLanguage(languageCode) {
66
+ return languageCode.split('-')[0];
67
+ }
68
+ function findBestTranslationMatch(translations, targetLanguage) {
69
+ if (!translations || !targetLanguage) return null;
70
+ const normalizedTarget = normalizeLanguageCode(targetLanguage);
71
+ const exactMatch = Object.keys(translations).find((key)=>normalizeLanguageCode(key) === normalizedTarget);
72
+ if (exactMatch) {
73
+ logger.debug(`Found exact translation match: ${exactMatch}`);
74
+ return exactMatch;
75
+ }
76
+ if (normalizedTarget.includes('-')) {
77
+ const baseLanguage = getBaseLanguage(normalizedTarget);
78
+ const baseMatch = Object.keys(translations).find((key)=>normalizeLanguageCode(key) === baseLanguage);
79
+ if (baseMatch) {
80
+ logger.debug(`Found base language translation match: ${baseMatch} (from ${targetLanguage})`);
81
+ return baseMatch;
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+ function isTranslatedChoices(questionTranslation) {
87
+ return (0, index_js_namespaceObject.isArray)(questionTranslation.choices);
88
+ }
89
+ function hasThankYouTranslation(translation) {
90
+ return !(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageHeader) || !(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageDescription) || !(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageCloseButtonText);
91
+ }
92
+ function mergeQuestionTranslation(question, targetLanguage) {
93
+ const translationKey = findBestTranslationMatch(question.translations, targetLanguage);
94
+ if (!translationKey) return {
95
+ question,
96
+ matchedKey: null,
97
+ hasChanges: false
98
+ };
99
+ const questionTranslation = question.translations?.[translationKey];
100
+ if (!questionTranslation) return {
101
+ question,
102
+ matchedKey: null,
103
+ hasChanges: false
104
+ };
105
+ const translated = {
106
+ ...question
107
+ };
108
+ let hasChanges = false;
109
+ if (!(0, index_js_namespaceObject.isUndefined)(questionTranslation.question)) {
110
+ translated.question = questionTranslation.question;
111
+ hasChanges = true;
112
+ }
113
+ if (!(0, index_js_namespaceObject.isUndefined)(questionTranslation.description)) {
114
+ translated.description = questionTranslation.description;
115
+ hasChanges = true;
116
+ }
117
+ if (!(0, index_js_namespaceObject.isUndefined)(questionTranslation.buttonText)) {
118
+ translated.buttonText = questionTranslation.buttonText;
119
+ hasChanges = true;
120
+ }
121
+ if ('link' in translated && !(0, index_js_namespaceObject.isUndefined)(questionTranslation.link)) {
122
+ translated.link = questionTranslation.link;
123
+ hasChanges = true;
124
+ }
125
+ if ('lowerBoundLabel' in translated && !(0, index_js_namespaceObject.isUndefined)(questionTranslation.lowerBoundLabel)) {
126
+ translated.lowerBoundLabel = questionTranslation.lowerBoundLabel;
127
+ hasChanges = true;
128
+ }
129
+ if ('upperBoundLabel' in translated && !(0, index_js_namespaceObject.isUndefined)(questionTranslation.upperBoundLabel)) {
130
+ translated.upperBoundLabel = questionTranslation.upperBoundLabel;
131
+ hasChanges = true;
132
+ }
133
+ if ('choices' in translated && isTranslatedChoices(questionTranslation)) {
134
+ translated.choices = questionTranslation.choices;
135
+ hasChanges = true;
136
+ }
137
+ return {
138
+ question: hasChanges ? translated : question,
139
+ matchedKey: hasChanges ? translationKey : null,
140
+ hasChanges
141
+ };
142
+ }
143
+ function applySurveyTranslation(survey, targetLanguage) {
144
+ const translationKey = findBestTranslationMatch(survey.translations, targetLanguage);
145
+ const translated = {
146
+ ...survey
147
+ };
148
+ let hasTranslation = false;
149
+ if (translationKey) {
150
+ const translation = survey.translations?.[translationKey];
151
+ if (translation) {
152
+ logger.info(`Applying survey-level translation for language: ${translationKey}`);
153
+ if (!(0, index_js_namespaceObject.isUndefined)(translation.name)) {
154
+ translated.name = translation.name;
155
+ hasTranslation = true;
156
+ }
157
+ if (translated.appearance) {
158
+ translated.appearance = {
159
+ ...translated.appearance
160
+ };
161
+ if (!(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageHeader)) {
162
+ translated.appearance.thankYouMessageHeader = translation.thankYouMessageHeader;
163
+ hasTranslation = true;
164
+ }
165
+ if (!(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageDescription)) {
166
+ translated.appearance.thankYouMessageDescription = translation.thankYouMessageDescription;
167
+ hasTranslation = true;
168
+ }
169
+ if (!(0, index_js_namespaceObject.isUndefined)(translation.thankYouMessageCloseButtonText)) {
170
+ translated.appearance.thankYouMessageCloseButtonText = translation.thankYouMessageCloseButtonText;
171
+ hasTranslation = true;
172
+ }
173
+ } else if (hasThankYouTranslation(translation)) hasTranslation = true;
174
+ }
175
+ }
176
+ const translatedResults = survey.questions.map((question)=>mergeQuestionTranslation(question, targetLanguage));
177
+ const translatedQuestions = translatedResults.map((result)=>result.question);
178
+ const anyQuestionTranslated = translatedResults.some((result)=>result.hasChanges);
179
+ let questionMatchedKey = null;
180
+ if (!translationKey) questionMatchedKey = translatedResults.find((result)=>result.matchedKey)?.matchedKey || null;
181
+ if (anyQuestionTranslated) {
182
+ translated.questions = translatedQuestions;
183
+ hasTranslation = true;
184
+ logger.info(`Applied question-level translations for language: ${targetLanguage}`);
185
+ }
186
+ return {
187
+ survey: translated,
188
+ matchedKey: hasTranslation ? translationKey || questionMatchedKey : null
189
+ };
190
+ }
191
+ exports.applySurveyTranslation = __webpack_exports__.applySurveyTranslation;
192
+ exports.detectSurveyLanguage = __webpack_exports__.detectSurveyLanguage;
193
+ exports.findBestTranslationMatch = __webpack_exports__.findBestTranslationMatch;
194
+ exports.getBaseLanguage = __webpack_exports__.getBaseLanguage;
195
+ exports.getLanguageFromStoredPersonProperties = __webpack_exports__.getLanguageFromStoredPersonProperties;
196
+ exports.normalizeLanguageCode = __webpack_exports__.normalizeLanguageCode;
197
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
198
+ "applySurveyTranslation",
199
+ "detectSurveyLanguage",
200
+ "findBestTranslationMatch",
201
+ "getBaseLanguage",
202
+ "getLanguageFromStoredPersonProperties",
203
+ "normalizeLanguageCode"
204
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
205
+ Object.defineProperty(exports, '__esModule', {
206
+ value: true
207
+ });
@@ -0,0 +1,158 @@
1
+ import { createLogger, isArray, isUndefined } from "../utils/index.mjs";
2
+ const logger = createLogger('[SurveyTranslations]');
3
+ function getTrimmedLanguage(value) {
4
+ return 'string' == typeof value && value.trim() ? value.trim() : null;
5
+ }
6
+ function getLanguageFromStoredPersonProperties(storedPersonProperties) {
7
+ if (!storedPersonProperties || 'object' != typeof storedPersonProperties || !('language' in storedPersonProperties)) return null;
8
+ return getTrimmedLanguage(storedPersonProperties.language);
9
+ }
10
+ function detectSurveyLanguage({ overrideLanguage, storedPersonProperties, locale }) {
11
+ const explicitLanguage = getTrimmedLanguage(overrideLanguage);
12
+ if (explicitLanguage) {
13
+ logger.info(`Using override display language: ${explicitLanguage}`);
14
+ return explicitLanguage;
15
+ }
16
+ const personLanguage = getLanguageFromStoredPersonProperties(storedPersonProperties);
17
+ if (personLanguage) {
18
+ logger.info(`Using person property language: ${personLanguage}`);
19
+ return personLanguage;
20
+ }
21
+ const detectedLocale = getTrimmedLanguage(locale);
22
+ if (detectedLocale) {
23
+ logger.info(`Using detected locale: ${detectedLocale}`);
24
+ return detectedLocale;
25
+ }
26
+ logger.info('No user language detected');
27
+ return null;
28
+ }
29
+ function normalizeLanguageCode(languageCode) {
30
+ return languageCode.toLowerCase();
31
+ }
32
+ function getBaseLanguage(languageCode) {
33
+ return languageCode.split('-')[0];
34
+ }
35
+ function findBestTranslationMatch(translations, targetLanguage) {
36
+ if (!translations || !targetLanguage) return null;
37
+ const normalizedTarget = normalizeLanguageCode(targetLanguage);
38
+ const exactMatch = Object.keys(translations).find((key)=>normalizeLanguageCode(key) === normalizedTarget);
39
+ if (exactMatch) {
40
+ logger.debug(`Found exact translation match: ${exactMatch}`);
41
+ return exactMatch;
42
+ }
43
+ if (normalizedTarget.includes('-')) {
44
+ const baseLanguage = getBaseLanguage(normalizedTarget);
45
+ const baseMatch = Object.keys(translations).find((key)=>normalizeLanguageCode(key) === baseLanguage);
46
+ if (baseMatch) {
47
+ logger.debug(`Found base language translation match: ${baseMatch} (from ${targetLanguage})`);
48
+ return baseMatch;
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ function isTranslatedChoices(questionTranslation) {
54
+ return isArray(questionTranslation.choices);
55
+ }
56
+ function hasThankYouTranslation(translation) {
57
+ return !isUndefined(translation.thankYouMessageHeader) || !isUndefined(translation.thankYouMessageDescription) || !isUndefined(translation.thankYouMessageCloseButtonText);
58
+ }
59
+ function mergeQuestionTranslation(question, targetLanguage) {
60
+ const translationKey = findBestTranslationMatch(question.translations, targetLanguage);
61
+ if (!translationKey) return {
62
+ question,
63
+ matchedKey: null,
64
+ hasChanges: false
65
+ };
66
+ const questionTranslation = question.translations?.[translationKey];
67
+ if (!questionTranslation) return {
68
+ question,
69
+ matchedKey: null,
70
+ hasChanges: false
71
+ };
72
+ const translated = {
73
+ ...question
74
+ };
75
+ let hasChanges = false;
76
+ if (!isUndefined(questionTranslation.question)) {
77
+ translated.question = questionTranslation.question;
78
+ hasChanges = true;
79
+ }
80
+ if (!isUndefined(questionTranslation.description)) {
81
+ translated.description = questionTranslation.description;
82
+ hasChanges = true;
83
+ }
84
+ if (!isUndefined(questionTranslation.buttonText)) {
85
+ translated.buttonText = questionTranslation.buttonText;
86
+ hasChanges = true;
87
+ }
88
+ if ('link' in translated && !isUndefined(questionTranslation.link)) {
89
+ translated.link = questionTranslation.link;
90
+ hasChanges = true;
91
+ }
92
+ if ('lowerBoundLabel' in translated && !isUndefined(questionTranslation.lowerBoundLabel)) {
93
+ translated.lowerBoundLabel = questionTranslation.lowerBoundLabel;
94
+ hasChanges = true;
95
+ }
96
+ if ('upperBoundLabel' in translated && !isUndefined(questionTranslation.upperBoundLabel)) {
97
+ translated.upperBoundLabel = questionTranslation.upperBoundLabel;
98
+ hasChanges = true;
99
+ }
100
+ if ('choices' in translated && isTranslatedChoices(questionTranslation)) {
101
+ translated.choices = questionTranslation.choices;
102
+ hasChanges = true;
103
+ }
104
+ return {
105
+ question: hasChanges ? translated : question,
106
+ matchedKey: hasChanges ? translationKey : null,
107
+ hasChanges
108
+ };
109
+ }
110
+ function applySurveyTranslation(survey, targetLanguage) {
111
+ const translationKey = findBestTranslationMatch(survey.translations, targetLanguage);
112
+ const translated = {
113
+ ...survey
114
+ };
115
+ let hasTranslation = false;
116
+ if (translationKey) {
117
+ const translation = survey.translations?.[translationKey];
118
+ if (translation) {
119
+ logger.info(`Applying survey-level translation for language: ${translationKey}`);
120
+ if (!isUndefined(translation.name)) {
121
+ translated.name = translation.name;
122
+ hasTranslation = true;
123
+ }
124
+ if (translated.appearance) {
125
+ translated.appearance = {
126
+ ...translated.appearance
127
+ };
128
+ if (!isUndefined(translation.thankYouMessageHeader)) {
129
+ translated.appearance.thankYouMessageHeader = translation.thankYouMessageHeader;
130
+ hasTranslation = true;
131
+ }
132
+ if (!isUndefined(translation.thankYouMessageDescription)) {
133
+ translated.appearance.thankYouMessageDescription = translation.thankYouMessageDescription;
134
+ hasTranslation = true;
135
+ }
136
+ if (!isUndefined(translation.thankYouMessageCloseButtonText)) {
137
+ translated.appearance.thankYouMessageCloseButtonText = translation.thankYouMessageCloseButtonText;
138
+ hasTranslation = true;
139
+ }
140
+ } else if (hasThankYouTranslation(translation)) hasTranslation = true;
141
+ }
142
+ }
143
+ const translatedResults = survey.questions.map((question)=>mergeQuestionTranslation(question, targetLanguage));
144
+ const translatedQuestions = translatedResults.map((result)=>result.question);
145
+ const anyQuestionTranslated = translatedResults.some((result)=>result.hasChanges);
146
+ let questionMatchedKey = null;
147
+ if (!translationKey) questionMatchedKey = translatedResults.find((result)=>result.matchedKey)?.matchedKey || null;
148
+ if (anyQuestionTranslated) {
149
+ translated.questions = translatedQuestions;
150
+ hasTranslation = true;
151
+ logger.info(`Applied question-level translations for language: ${targetLanguage}`);
152
+ }
153
+ return {
154
+ survey: translated,
155
+ matchedKey: hasTranslation ? translationKey || questionMatchedKey : null
156
+ };
157
+ }
158
+ export { applySurveyTranslation, detectSurveyLanguage, findBestTranslationMatch, getBaseLanguage, getLanguageFromStoredPersonProperties, normalizeLanguageCode };
@@ -1 +1 @@
1
- {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../src/testing/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhC,eAAO,MAAM,IAAI,GAAU,GAAG,MAAM,KAAG,OAAO,CAAC,IAAI,CAElD,CAAA;AAED,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAQpD,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,UAAU,GAAG,KAAG,GAIzC,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,CAAC,OAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAM5E,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAI9C,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAO,MAQnC,CAAA"}
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../src/testing/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhC,eAAO,MAAM,IAAI,GAAU,GAAG,MAAM,KAAG,OAAO,CAAC,IAAI,CAElD,CAAA;AAED,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAQpD,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,UAAU,GAAG,KAAG,GAIzC,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,CAAC,OAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAM5E,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAI9C,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAO,MASnC,CAAA"}
@@ -60,6 +60,7 @@ const delay = (ms)=>new Promise((resolve)=>{
60
60
  setTimeout(resolve, ms);
61
61
  });
62
62
  const createMockLogger = ()=>({
63
+ debug: jest.fn((...args)=>console.debug(...args)),
63
64
  info: jest.fn((...args)=>console.log(...args)),
64
65
  warn: jest.fn((...args)=>console.warn(...args)),
65
66
  error: jest.fn((...args)=>console.error(...args)),
@@ -27,6 +27,7 @@ const delay = (ms)=>new Promise((resolve)=>{
27
27
  setTimeout(resolve, ms);
28
28
  });
29
29
  const createMockLogger = ()=>({
30
+ debug: jest.fn((...args)=>console.debug(...args)),
30
31
  info: jest.fn((...args)=>console.log(...args)),
31
32
  warn: jest.fn((...args)=>console.warn(...args)),
32
33
  error: jest.fn((...args)=>console.error(...args)),
package/dist/types.d.ts CHANGED
@@ -318,6 +318,15 @@ export type PostHogRemoteConfig = {
318
318
  capturePerformance?: boolean | {
319
319
  [key: string]: JsonType;
320
320
  };
321
+ /**
322
+ * Logs feature remote config. When a map, `captureConsoleLogs` (boolean)
323
+ * is the local opt-in flag for `console.*` autocapture (read by the JS
324
+ * SDK's `PostHogLogs` extension to decide whether to load the autocapture
325
+ * bundle).
326
+ */
327
+ logs?: boolean | {
328
+ [key: string]: JsonType;
329
+ };
321
330
  };
322
331
  export type FeatureFlagValue = string | boolean;
323
332
  /**
@@ -534,23 +543,39 @@ export interface SurveyValidationRule {
534
543
  value?: number;
535
544
  errorMessage?: string;
536
545
  }
546
+ export interface SurveyTranslation {
547
+ name?: string;
548
+ thankYouMessageHeader?: string;
549
+ thankYouMessageDescription?: string;
550
+ thankYouMessageCloseButtonText?: string;
551
+ }
552
+ export interface SurveyQuestionTranslation {
553
+ question?: string;
554
+ description?: string | null;
555
+ buttonText?: string;
556
+ link?: string | null;
557
+ lowerBoundLabel?: string;
558
+ upperBoundLabel?: string;
559
+ choices?: string[];
560
+ }
537
561
  type SurveyQuestionBase = {
538
562
  question: string;
539
563
  id: string;
540
- description?: string;
564
+ description?: string | null;
541
565
  descriptionContentType?: SurveyQuestionDescriptionContentType;
542
566
  optional?: boolean;
543
567
  buttonText?: string;
544
568
  originalQuestionIndex: number;
545
569
  branching?: NextQuestionBranching | EndBranching | ResponseBasedBranching | SpecificQuestionBranching;
546
570
  validation?: SurveyValidationRule[];
571
+ translations?: Record<string, SurveyQuestionTranslation>;
547
572
  };
548
573
  export type BasicSurveyQuestion = SurveyQuestionBase & {
549
574
  type: SurveyQuestionType.Open;
550
575
  };
551
576
  export type LinkSurveyQuestion = SurveyQuestionBase & {
552
577
  type: SurveyQuestionType.Link;
553
- link?: string;
578
+ link?: string | null;
554
579
  };
555
580
  export type RatingSurveyQuestion = SurveyQuestionBase & {
556
581
  type: SurveyQuestionType.Rating;
@@ -601,6 +626,8 @@ export type SpecificQuestionBranching = {
601
626
  export type SurveyResponse = {
602
627
  surveys: Survey[];
603
628
  };
629
+ export type SurveyResponseValue = string | number | string[] | null;
630
+ export type SurveyResponses = Record<string, SurveyResponseValue>;
604
631
  export type SurveyCallback = (surveys: Survey[]) => void;
605
632
  export declare enum SurveyMatchType {
606
633
  Regex = "regex",
@@ -638,6 +665,7 @@ export type Survey = {
638
665
  name: string;
639
666
  description?: string;
640
667
  type: SurveyType;
668
+ translations?: Record<string, SurveyTranslation>;
641
669
  feature_flag_keys?: {
642
670
  key: string;
643
671
  value?: string;
@@ -696,6 +724,7 @@ export type ActionStepType = {
696
724
  url_matching?: ActionStepStringMatching;
697
725
  };
698
726
  export type Logger = {
727
+ debug: (...args: any[]) => void;
699
728
  info: (...args: any[]) => void;
700
729
  warn: (...args: any[]) => void;
701
730
  error: (...args: any[]) => void;