mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-07 00:40:10 -06:00
chore: Chinese to iso languages (#2794)
Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com>
This commit is contained in:
committed by
GitHub
parent
785afd4bda
commit
d27da8927e
@@ -0,0 +1,119 @@
|
||||
// migration script for converting zh code for chinese language to zh-Hans
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import {
|
||||
TSurveyLanguage,
|
||||
TSurveyQuestion,
|
||||
TSurveyThankYouCard,
|
||||
TSurveyWelcomeCard,
|
||||
} from "@formbricks/types/surveys";
|
||||
import {
|
||||
updateLanguageCodeForQuestion,
|
||||
updateLanguageCodeForThankYouCard,
|
||||
updateLanguageCodeForWelcomeCard,
|
||||
} from "./lib/utils";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const main = async () => {
|
||||
await prisma.$transaction(
|
||||
async (tx) => {
|
||||
const startTime = Date.now();
|
||||
console.log("Starting data migration...");
|
||||
|
||||
// Fetch all surveys
|
||||
const surveys: {
|
||||
id: string;
|
||||
questions: TSurveyQuestion[];
|
||||
welcomeCard: TSurveyWelcomeCard;
|
||||
thankYouCard: TSurveyThankYouCard;
|
||||
languages: TSurveyLanguage[];
|
||||
}[] = await tx.survey.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
questions: true,
|
||||
welcomeCard: true,
|
||||
thankYouCard: true,
|
||||
languages: {
|
||||
select: {
|
||||
default: true,
|
||||
enabled: true,
|
||||
language: {
|
||||
select: {
|
||||
id: true,
|
||||
code: true,
|
||||
alias: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (surveys.length === 0) {
|
||||
// stop the migration if there are no surveys
|
||||
console.log("No Surveys found");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Total surveys found:${surveys.length}`);
|
||||
let transformedSurveyCount = 0;
|
||||
|
||||
const surveysWithChineseTranslations = surveys.filter((survey) =>
|
||||
survey.languages.some((surveyLanguage) => surveyLanguage.language.code === "zh")
|
||||
);
|
||||
|
||||
const updatePromises = surveysWithChineseTranslations.map((survey) => {
|
||||
transformedSurveyCount++;
|
||||
const updatedSurvey = structuredClone(survey);
|
||||
|
||||
// Update cards and questions
|
||||
updatedSurvey.welcomeCard = updateLanguageCodeForWelcomeCard(survey.welcomeCard, "zh", "zh-Hans");
|
||||
updatedSurvey.thankYouCard = updateLanguageCodeForThankYouCard(survey.thankYouCard, "zh", "zh-Hans");
|
||||
updatedSurvey.questions = survey.questions.map((question) =>
|
||||
updateLanguageCodeForQuestion(question, "zh", "zh-Hans")
|
||||
);
|
||||
|
||||
// Return the update promise
|
||||
return tx.survey.update({
|
||||
where: { id: survey.id },
|
||||
data: {
|
||||
welcomeCard: updatedSurvey.welcomeCard,
|
||||
thankYouCard: updatedSurvey.thankYouCard,
|
||||
questions: updatedSurvey.questions,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(updatePromises);
|
||||
|
||||
console.log(transformedSurveyCount, " surveys transformed");
|
||||
|
||||
console.log("updating languages");
|
||||
await tx.language.updateMany({
|
||||
where: {
|
||||
code: "zh",
|
||||
},
|
||||
data: {
|
||||
code: "zh-Hans",
|
||||
},
|
||||
});
|
||||
console.log("survey language updated");
|
||||
const endTime = Date.now();
|
||||
console.log(`Data migration completed. Total time: ${(endTime - startTime) / 1000}s`);
|
||||
},
|
||||
{
|
||||
timeout: 180000, // 3 minutes
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
main()
|
||||
.catch((e: Error) => {
|
||||
console.error("Error during migration: ", e.message);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
@@ -0,0 +1,259 @@
|
||||
import {
|
||||
TI18nString,
|
||||
TSurveyCTAQuestion,
|
||||
TSurveyChoice,
|
||||
TSurveyConsentQuestion,
|
||||
TSurveyMatrixQuestion,
|
||||
TSurveyMultipleChoiceQuestion,
|
||||
TSurveyNPSQuestion,
|
||||
TSurveyOpenTextQuestion,
|
||||
TSurveyQuestion,
|
||||
TSurveyRatingQuestion,
|
||||
TSurveyThankYouCard,
|
||||
TSurveyWelcomeCard,
|
||||
ZSurveyAddressQuestion,
|
||||
ZSurveyCTAQuestion,
|
||||
ZSurveyCalQuestion,
|
||||
ZSurveyConsentQuestion,
|
||||
ZSurveyFileUploadQuestion,
|
||||
ZSurveyMatrixQuestion,
|
||||
ZSurveyMultipleChoiceQuestion,
|
||||
ZSurveyNPSQuestion,
|
||||
ZSurveyOpenTextQuestion,
|
||||
ZSurveyPictureSelectionQuestion,
|
||||
ZSurveyQuestion,
|
||||
ZSurveyRatingQuestion,
|
||||
ZSurveyThankYouCard,
|
||||
ZSurveyWelcomeCard,
|
||||
} from "@formbricks/types/surveys";
|
||||
|
||||
export const updateLanguageCode = (i18nString: TI18nString, oldCode: string, newCode: string) => {
|
||||
const updatedI18nString = structuredClone(i18nString);
|
||||
if (Object.keys(i18nString).includes(oldCode)) {
|
||||
const text = i18nString[oldCode];
|
||||
delete updatedI18nString[oldCode];
|
||||
updatedI18nString[newCode] = text;
|
||||
}
|
||||
return updatedI18nString;
|
||||
};
|
||||
|
||||
export const updateChoiceLanguage = (
|
||||
choice: TSurveyChoice,
|
||||
oldCode: string,
|
||||
newCode: string
|
||||
): TSurveyChoice => {
|
||||
if (typeof choice.label !== "undefined" && Object.keys(choice.label).includes(oldCode)) {
|
||||
return {
|
||||
...choice,
|
||||
label: updateLanguageCode(choice.label, oldCode, newCode),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...choice,
|
||||
label: choice.label,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const updateLanguageCodeForWelcomeCard = (
|
||||
welcomeCard: TSurveyWelcomeCard,
|
||||
oldCode: string,
|
||||
newCode: string
|
||||
) => {
|
||||
const clonedWelcomeCard = structuredClone(welcomeCard);
|
||||
if (typeof welcomeCard.headline !== "undefined" && Object.keys(welcomeCard.headline).includes(oldCode)) {
|
||||
clonedWelcomeCard.headline = updateLanguageCode(welcomeCard.headline, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (typeof welcomeCard.html !== "undefined" && Object.keys(welcomeCard.html).includes(oldCode)) {
|
||||
clonedWelcomeCard.html = updateLanguageCode(welcomeCard.html, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof welcomeCard.buttonLabel !== "undefined" &&
|
||||
Object.keys(welcomeCard.buttonLabel).includes(oldCode)
|
||||
) {
|
||||
clonedWelcomeCard.buttonLabel = updateLanguageCode(welcomeCard.buttonLabel, oldCode, newCode);
|
||||
}
|
||||
|
||||
return ZSurveyWelcomeCard.parse(clonedWelcomeCard);
|
||||
};
|
||||
|
||||
export const updateLanguageCodeForThankYouCard = (
|
||||
thankYouCard: TSurveyThankYouCard,
|
||||
oldCode: string,
|
||||
newCode: string
|
||||
) => {
|
||||
const clonedThankYouCard = structuredClone(thankYouCard);
|
||||
if (typeof thankYouCard.headline !== "undefined" && Object.keys(thankYouCard.headline).includes(oldCode)) {
|
||||
clonedThankYouCard.headline = updateLanguageCode(thankYouCard.headline, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof thankYouCard.subheader !== "undefined" &&
|
||||
Object.keys(thankYouCard.subheader).includes(oldCode)
|
||||
) {
|
||||
clonedThankYouCard.subheader = updateLanguageCode(thankYouCard.subheader, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof thankYouCard.buttonLabel !== "undefined" &&
|
||||
Object.keys(thankYouCard.buttonLabel).includes(oldCode)
|
||||
) {
|
||||
clonedThankYouCard.buttonLabel = updateLanguageCode(thankYouCard.buttonLabel, oldCode, newCode);
|
||||
}
|
||||
return ZSurveyThankYouCard.parse(clonedThankYouCard);
|
||||
};
|
||||
|
||||
export const updateLanguageCodeForQuestion = (
|
||||
question: TSurveyQuestion,
|
||||
oldCode: string,
|
||||
newCode: string
|
||||
) => {
|
||||
const clonedQuestion = structuredClone(question);
|
||||
//common question properties
|
||||
if (typeof question.headline !== "undefined" && Object.keys(question.headline).includes(oldCode)) {
|
||||
clonedQuestion.headline = updateLanguageCode(question.headline, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (typeof question.subheader !== "undefined" && Object.keys(question.subheader).includes(oldCode)) {
|
||||
clonedQuestion.subheader = updateLanguageCode(question.subheader, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (typeof question.buttonLabel !== "undefined" && Object.keys(question.buttonLabel).includes(oldCode)) {
|
||||
clonedQuestion.buttonLabel = updateLanguageCode(question.buttonLabel, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof question.backButtonLabel !== "undefined" &&
|
||||
Object.keys(question.backButtonLabel).includes(oldCode)
|
||||
) {
|
||||
clonedQuestion.backButtonLabel = updateLanguageCode(question.backButtonLabel, oldCode, newCode);
|
||||
}
|
||||
|
||||
switch (question.type) {
|
||||
case "openText":
|
||||
if (
|
||||
typeof question.placeholder !== "undefined" &&
|
||||
Object.keys(question.placeholder).includes(oldCode)
|
||||
) {
|
||||
(clonedQuestion as TSurveyOpenTextQuestion).placeholder = updateLanguageCode(
|
||||
question.placeholder,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
return ZSurveyOpenTextQuestion.parse(clonedQuestion);
|
||||
|
||||
case "multipleChoiceSingle":
|
||||
case "multipleChoiceMulti":
|
||||
(clonedQuestion as TSurveyMultipleChoiceQuestion).choices = question.choices.map((choice) => {
|
||||
return updateChoiceLanguage(choice, oldCode, newCode);
|
||||
});
|
||||
if (
|
||||
typeof question.otherOptionPlaceholder !== "undefined" &&
|
||||
Object.keys(question.otherOptionPlaceholder).includes(oldCode)
|
||||
) {
|
||||
(clonedQuestion as TSurveyMultipleChoiceQuestion).otherOptionPlaceholder = updateLanguageCode(
|
||||
question.otherOptionPlaceholder,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
return ZSurveyMultipleChoiceQuestion.parse(clonedQuestion);
|
||||
|
||||
case "cta":
|
||||
if (
|
||||
typeof question.dismissButtonLabel !== "undefined" &&
|
||||
Object.keys(question.dismissButtonLabel).includes(oldCode)
|
||||
) {
|
||||
(clonedQuestion as TSurveyCTAQuestion).dismissButtonLabel = updateLanguageCode(
|
||||
question.dismissButtonLabel,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
if (typeof question.html !== "undefined" && Object.keys(question.html).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyCTAQuestion).html = updateLanguageCode(question.html, oldCode, newCode);
|
||||
}
|
||||
return ZSurveyCTAQuestion.parse(clonedQuestion);
|
||||
|
||||
case "consent":
|
||||
if (typeof question.html !== "undefined" && Object.keys(question.html).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyConsentQuestion).html = updateLanguageCode(question.html, oldCode, newCode);
|
||||
}
|
||||
|
||||
if (typeof question.label !== "undefined" && Object.keys(question.label).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyConsentQuestion).label = updateLanguageCode(
|
||||
question.label,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
return ZSurveyConsentQuestion.parse(clonedQuestion);
|
||||
|
||||
case "nps":
|
||||
if (typeof question.lowerLabel !== "undefined" && Object.keys(question.lowerLabel).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyNPSQuestion).lowerLabel = updateLanguageCode(
|
||||
question.lowerLabel,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
if (typeof question.upperLabel !== "undefined" && Object.keys(question.upperLabel).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyNPSQuestion).upperLabel = updateLanguageCode(
|
||||
question.upperLabel,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
return ZSurveyNPSQuestion.parse(clonedQuestion);
|
||||
|
||||
case "rating":
|
||||
if (typeof question.lowerLabel !== "undefined" && Object.keys(question.lowerLabel).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyRatingQuestion).lowerLabel = updateLanguageCode(
|
||||
question.lowerLabel,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof question.upperLabel !== "undefined" && Object.keys(question.upperLabel).includes(oldCode)) {
|
||||
(clonedQuestion as TSurveyRatingQuestion).upperLabel = updateLanguageCode(
|
||||
question.upperLabel,
|
||||
oldCode,
|
||||
newCode
|
||||
);
|
||||
}
|
||||
return ZSurveyRatingQuestion.parse(clonedQuestion);
|
||||
|
||||
case "matrix":
|
||||
(clonedQuestion as TSurveyMatrixQuestion).rows = question.rows.map((row) => {
|
||||
if (typeof row !== "undefined" && Object.keys(row).includes(oldCode)) {
|
||||
return updateLanguageCode(row, oldCode, newCode);
|
||||
} else return row;
|
||||
});
|
||||
|
||||
(clonedQuestion as TSurveyMatrixQuestion).columns = question.columns.map((column) => {
|
||||
if (typeof column !== "undefined" && Object.keys(column).includes(oldCode)) {
|
||||
return updateLanguageCode(column, oldCode, newCode);
|
||||
} else return column;
|
||||
});
|
||||
return ZSurveyMatrixQuestion.parse(clonedQuestion);
|
||||
|
||||
case "fileUpload":
|
||||
return ZSurveyFileUploadQuestion.parse(clonedQuestion);
|
||||
|
||||
case "pictureSelection":
|
||||
return ZSurveyPictureSelectionQuestion.parse(clonedQuestion);
|
||||
|
||||
case "cal":
|
||||
return ZSurveyCalQuestion.parse(clonedQuestion);
|
||||
|
||||
case "address":
|
||||
return ZSurveyAddressQuestion.parse(clonedQuestion);
|
||||
|
||||
default:
|
||||
return ZSurveyQuestion.parse(clonedQuestion);
|
||||
}
|
||||
};
|
||||
@@ -38,7 +38,8 @@
|
||||
"data-migration:v2.1": "pnpm data-migration:extended-noCodeActions",
|
||||
"data-migration:adds_app_and_website_status_indicator": "ts-node ./data-migrations/20240610055828_adds_app_and_website_status_indicators/data-migration.ts",
|
||||
"data-migration:product-config": "ts-node ./data-migrations/20240612115151_adds_product_config/data-migration.ts",
|
||||
"data-migration:v2.2": "pnpm data-migration:adds_app_and_website_status_indicator && pnpm data-migration:product-config && pnpm data-migration:pricing-v2"
|
||||
"data-migration:v2.2": "pnpm data-migration:adds_app_and_website_status_indicator && pnpm data-migration:product-config && pnpm data-migration:pricing-v2",
|
||||
"data-migration:zh-to-zh-Hans": "ts-node ./data-migrations/20240625101352_update_zh_to_zh-Hans/data-migration.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^5.15.1",
|
||||
|
||||
@@ -1045,8 +1045,12 @@ export const iso639Languages = [
|
||||
english: "Zhuang; Chuang",
|
||||
},
|
||||
{
|
||||
alpha2: "zh",
|
||||
english: "Chinese",
|
||||
alpha2: "zh-Hans",
|
||||
english: "Chinese (Simplified)",
|
||||
},
|
||||
{
|
||||
alpha2: "zh-Hant",
|
||||
english: "Chinese (Traditional)",
|
||||
},
|
||||
{
|
||||
alpha2: "zu",
|
||||
|
||||
Reference in New Issue
Block a user