Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/survey-core/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,11 @@ export class Base implements IObjectValueContext {
protected mergeLocalizationObj(obj: Base, locales?: Array<string>): void {
this.mergeLocalizationInObjectCore(obj, locales);
this.mergeLocalizationInArrays(obj, locales);
const orgObj = obj.getOriginalObj();
const org = this.getOriginalObj();
if (orgObj !== obj && org !== this) {
org.mergeLocalizationObj(orgObj, locales);
}
}
private mergeLocalizationInObjectCore(obj: Base, locales?: Array<string>): void {
if (!this.canMergeObj(obj)) return;
Expand All @@ -471,7 +476,6 @@ export class Base implements IObjectValueContext {
if (!obj || typeof obj.mergeLocalizationObj !== "function") return false;
const self: any = this;
if (obj["name"] && self.name !== obj["name"]) return false;
if (obj["value"] && self.value !== obj["value"]) return false;
return true;
}
private mergeLocalizationInArrays(obj: Base, locales?: Array<string>): void {
Expand Down
6 changes: 6 additions & 0 deletions packages/survey-core/src/question_custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,12 @@ export class QuestionCustomModel extends QuestionCustomModelBase {
public getOriginalObj(): Base {
return this.questionWrapper;
}
public getOriginalByProperty(propName: string): Base {
const inProps = this.customQuestion?.json?.inheritBaseProps;
let isInheritedProp = inProps === true || (Array.isArray(inProps) && inProps.indexOf(propName) > -1);
if (!isInheritedProp && !!Serializer.findProperty("question", propName)) return this;
return super.getOriginalByProperty(propName);
}
protected createWrapper(): void {
this.questionWrapper = this.createQuestion();
this.createDynamicProperties(this.questionWrapper);
Expand Down
122 changes: 122 additions & 0 deletions packages/survey-core/tests/question_customtests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4253,3 +4253,125 @@ QUnit.test("Composite: allow to make the custom number rendering", function (ass

ComponentCollection.Instance.clear();
});
QUnit.test("Single: Merge with separate locale strings, Bug#10771", (assert) => {
ComponentCollection.Instance.add({
name: "newquestion",
inheritBaseProps: ["choices"],
questionJSON:
{
type: "dropdown",
}
});
var survey = new SurveyModel({
elements: [{
type: "newquestion",
name: "q1",
title: { default: "Title", de: "Titel" },
description: { default: "Description", de: "Beschreibung" },
choices: [{ value: 1, text: { default: "item en", de: "item de" } }]
}]
});
const plainJSON = survey.toJSON({ storeLocaleStrings: false });
assert.deepEqual(plainJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
choices: [1]
}, "check plain json");
const enJSON = survey.getLocalizationJSON(["default"]);
assert.deepEqual(enJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: "Title",
description: "Description",
choices: [{ value: 1, text: "item en" }]
}, "check en json");
const deJSON = survey.getLocalizationJSON(["de"]);
assert.deepEqual(deJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: "Titel",
description: "Beschreibung",
choices: [{ value: 1, text: "item de" }]
}, "check de json");
const mergedSurvey = new SurveyModel(plainJSON);
mergedSurvey.mergeLocalizationJSON(enJSON);
mergedSurvey.mergeLocalizationJSON(deJSON);
assert.deepEqual(mergedSurvey.toJSON().pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: { default: "Title", de: "Titel" },
description: { default: "Description", de: "Beschreibung" },
choices: [{ value: 1, text: { default: "item en", de: "item de" } }]
}, "check merged json");
ComponentCollection.Instance.clear();
});
QUnit.test("Composite: Merge with separate locale strings, Bug#10771", (assert) => {
ComponentCollection.Instance.add(<any>{
name: "newquestion",
elementsJSON:
[{
type: "dropdown",
name: "myQuestion",
}],
onInit() {
Serializer.addProperty("newquestion", {
name: "myChoices:choiceitem[]",
});
},
onLoaded(question: QuestionCompositeModel) {
this.setChoices(question);
},
onPropertyChanged(question: QuestionCompositeModel, propertyName: string) {
if (propertyName == "myChoices") {
this.setChoices(question);
}
},
setChoices: (question: QuestionCompositeModel) => {
const choices = question.myChoices;
const dropdown = question.contentPanel.getQuestionByName("myQuestion") as QuestionDropdownModel;
dropdown.choices = choices;
}
});
var survey = new SurveyModel({
elements: [{
type: "newquestion",
name: "q1",
title: { default: "Title", de: "Titel" },
description: { default: "Description", de: "Beschreibung" },
myChoices: [{ value: 1, text: { default: "item en", de: "item de" } }]
}]
});
const plainJSON = survey.toJSON({ storeLocaleStrings: false });
assert.deepEqual(plainJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
myChoices: [1]
}, "check plain json");
const enJSON = survey.getLocalizationJSON(["default"]);
assert.deepEqual(enJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: "Title",
description: "Description",
myChoices: [{ value: 1, text: "item en" }]
}, "check en json");
const deJSON = survey.getLocalizationJSON(["de"]);
assert.deepEqual(deJSON.pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: "Titel",
description: "Beschreibung",
myChoices: [{ value: 1, text: "item de" }]
}, "check de json");
const mergedSurvey = new SurveyModel(plainJSON);
mergedSurvey.mergeLocalizationJSON(enJSON);
mergedSurvey.mergeLocalizationJSON(deJSON);
assert.deepEqual(mergedSurvey.toJSON().pages[0].elements[0], {
type: "newquestion",
name: "q1",
title: { default: "Title", de: "Titel" },
description: { default: "Description", de: "Beschreibung" },
myChoices: [{ value: 1, text: { default: "item en", de: "item de" } }]
}, "check merged json");
ComponentCollection.Instance.clear();
});