mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 18:30:32 -06:00
feat: add i18n utils tests and update multi-language survey components
This commit is contained in:
@@ -119,8 +119,9 @@ describe("Auth Utils", () => {
|
||||
});
|
||||
|
||||
test("should generate different hashes for same password", async () => {
|
||||
const hash1 = await hashPassword(password);
|
||||
const hash2 = await hashPassword(password);
|
||||
// Hash twice in parallel so the test doesn't incur two full bcrypt rounds sequentially.
|
||||
// Running them concurrently keeps the assertion meaningful while avoiding unnecessary timeouts.
|
||||
const [hash1, hash2] = await Promise.all([hashPassword(password), hashPassword(password)]);
|
||||
|
||||
expect(hash1).not.toBe(hash2);
|
||||
expect(await verifyPassword(password, hash1)).toBe(true);
|
||||
|
||||
@@ -62,7 +62,10 @@ const validateLanguages = (languages: Language[], t: TFunction) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the chosen alias matches an ISO identifier of a language that hasn't been added
|
||||
// Prevent choosing an alias that clashes with the ISO code of some other
|
||||
// language. Without this guard users could create ambiguous language entries
|
||||
// (e.g. alias "nl" pointing to a non-Dutch language) which later breaks the
|
||||
// dropdowns that rely on ISO identifiers.
|
||||
for (const alias of languageAliases) {
|
||||
if (iso639Languages.some((language) => language.alpha2 === alias && !languageCodes.includes(alias))) {
|
||||
toast.error(t("environments.project.languages.conflict_between_selected_alias_and_another_language"), {
|
||||
|
||||
@@ -43,8 +43,10 @@ export function LanguageSelect({ language, onLanguageChange, disabled, locale }:
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const getLabelForLocale = (item: TIso639Language) =>
|
||||
item.label[locale] ?? item.label["en-US"];
|
||||
// Most ISO entries don't ship with every locale translation, so fall back to
|
||||
// English to keep the dropdown readable for locales such as Dutch that were
|
||||
// added recently.
|
||||
const getLabelForLocale = (item: TIso639Language) => item.label[locale] ?? item.label["en-US"];
|
||||
|
||||
const filteredItems = items.filter((item) =>
|
||||
getLabelForLocale(item).toLowerCase().includes(searchTerm.toLowerCase())
|
||||
|
||||
17
packages/i18n-utils/src/utils.test.ts
Normal file
17
packages/i18n-utils/src/utils.test.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { getLanguageLabel } from "./utils";
|
||||
|
||||
describe("getLanguageLabel", () => {
|
||||
test("returns locale specific label when available", () => {
|
||||
expect(getLanguageLabel("de", "de-DE")).toBe("Deutsch");
|
||||
});
|
||||
|
||||
test("falls back to English when locale specific label is missing", () => {
|
||||
// Language "aa" (Afar) does not currently ship with a Dutch translation.
|
||||
expect(getLanguageLabel("aa", "nl-NL")).toBe("Afar");
|
||||
});
|
||||
|
||||
test("returns undefined for unknown language codes", () => {
|
||||
expect(getLanguageLabel("zz", "en-US")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -2613,6 +2613,16 @@ export const iso639Languages: TIso639Language[] = [
|
||||
|
||||
export const getLanguageLabel = (languageCode: string, locale: string): string | undefined => {
|
||||
const language = iso639Languages.find((lang) => lang.alpha2 === languageCode);
|
||||
// Type assertion to tell TypeScript that we know the structure of label
|
||||
return language?.label[locale as keyof typeof language.label];
|
||||
if (!language) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to read the label for the requested locale. Not every ISO-639 entry
|
||||
// has translations for every UI locale (for example Dutch strings were added
|
||||
// later), so we gracefully fall back to English when a localized label is
|
||||
// missing. Consumers expect a non-empty label in dropdowns and status chips,
|
||||
// so returning "en-US" keeps the UI readable instead of rendering nothing.
|
||||
const localizedLabel = language.label[locale as keyof typeof language.label];
|
||||
|
||||
return localizedLabel ?? language.label["en-US"];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user