Add langcode definitions to identitty-generator languages (#1383)

This commit is contained in:
Leendert de Borst
2025-11-22 21:33:31 +00:00
committed by Leendert de Borst
parent b1d12af7dd
commit 51dc4d2844
11 changed files with 486 additions and 33 deletions
@@ -242,6 +242,12 @@ interface ILanguageOption {
* The flag emoji for the language (e.g., "🇬🇧", "🇳🇱", "🇩🇪")
*/
flag: string;
/**
* Alternative language codes that map to this identity generator language.
* Used for matching UI locale codes to identity generator languages.
* For example, "en-US", "en-GB", "en-CA" all map to "en"
*/
alternativeCodes?: string[];
}
/**
* Gets all available languages for identity generation.
@@ -249,6 +255,20 @@ interface ILanguageOption {
* @returns Array of language options
*/
declare function getAvailableLanguages(): ILanguageOption[];
/**
* Maps a UI language code to an identity generator language code.
* If no explicit match is found, returns null to indicate no preference.
*
* @param uiLanguageCode - The UI language code (e.g., "en", "en-US", "nl-NL", "de-DE", "fr")
* @returns The matching identity generator language code or null if no match
*
* @example
* mapUiLanguageToIdentityLanguage("en-US") // returns "en"
* mapUiLanguageToIdentityLanguage("nl") // returns "nl"
* mapUiLanguageToIdentityLanguage("de-CH") // returns "de"
* mapUiLanguageToIdentityLanguage("fr") // returns null (no French identity generator)
*/
declare function mapUiLanguageToIdentityLanguage(uiLanguageCode: string | null | undefined): string | null;
/**
* Creates a new identity generator based on the language.
@@ -265,4 +285,4 @@ declare const CreateIdentityGenerator: (language: string) => IdentityGenerator;
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages };
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages, mapUiLanguageToIdentityLanguage };
@@ -34,7 +34,8 @@ __export(index_exports, {
UsernameEmailGenerator: () => UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions: () => convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges: () => getAvailableAgeRanges,
getAvailableLanguages: () => getAvailableLanguages
getAvailableLanguages: () => getAvailableLanguages,
mapUiLanguageToIdentityLanguage: () => mapUiLanguageToIdentityLanguage
});
module.exports = __toCommonJS(index_exports);
@@ -5926,11 +5927,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5964,5 +6003,6 @@ var CreateUsernameEmailGenerator = () => {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
});
@@ -5890,11 +5890,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5927,5 +5965,6 @@ export {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
};
@@ -242,6 +242,12 @@ interface ILanguageOption {
* The flag emoji for the language (e.g., "🇬🇧", "🇳🇱", "🇩🇪")
*/
flag: string;
/**
* Alternative language codes that map to this identity generator language.
* Used for matching UI locale codes to identity generator languages.
* For example, "en-US", "en-GB", "en-CA" all map to "en"
*/
alternativeCodes?: string[];
}
/**
* Gets all available languages for identity generation.
@@ -249,6 +255,20 @@ interface ILanguageOption {
* @returns Array of language options
*/
declare function getAvailableLanguages(): ILanguageOption[];
/**
* Maps a UI language code to an identity generator language code.
* If no explicit match is found, returns null to indicate no preference.
*
* @param uiLanguageCode - The UI language code (e.g., "en", "en-US", "nl-NL", "de-DE", "fr")
* @returns The matching identity generator language code or null if no match
*
* @example
* mapUiLanguageToIdentityLanguage("en-US") // returns "en"
* mapUiLanguageToIdentityLanguage("nl") // returns "nl"
* mapUiLanguageToIdentityLanguage("de-CH") // returns "de"
* mapUiLanguageToIdentityLanguage("fr") // returns null (no French identity generator)
*/
declare function mapUiLanguageToIdentityLanguage(uiLanguageCode: string | null | undefined): string | null;
/**
* Creates a new identity generator based on the language.
@@ -265,4 +285,4 @@ declare const CreateIdentityGenerator: (language: string) => IdentityGenerator;
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages };
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages, mapUiLanguageToIdentityLanguage };
@@ -34,7 +34,8 @@ __export(index_exports, {
UsernameEmailGenerator: () => UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions: () => convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges: () => getAvailableAgeRanges,
getAvailableLanguages: () => getAvailableLanguages
getAvailableLanguages: () => getAvailableLanguages,
mapUiLanguageToIdentityLanguage: () => mapUiLanguageToIdentityLanguage
});
module.exports = __toCommonJS(index_exports);
@@ -5926,11 +5927,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5964,5 +6003,6 @@ var CreateUsernameEmailGenerator = () => {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
});
@@ -5890,11 +5890,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5927,5 +5965,6 @@ export {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
};
@@ -242,6 +242,12 @@ interface ILanguageOption {
* The flag emoji for the language (e.g., "🇬🇧", "🇳🇱", "🇩🇪")
*/
flag: string;
/**
* Alternative language codes that map to this identity generator language.
* Used for matching UI locale codes to identity generator languages.
* For example, "en-US", "en-GB", "en-CA" all map to "en"
*/
alternativeCodes?: string[];
}
/**
* Gets all available languages for identity generation.
@@ -249,6 +255,20 @@ interface ILanguageOption {
* @returns Array of language options
*/
declare function getAvailableLanguages(): ILanguageOption[];
/**
* Maps a UI language code to an identity generator language code.
* If no explicit match is found, returns null to indicate no preference.
*
* @param uiLanguageCode - The UI language code (e.g., "en", "en-US", "nl-NL", "de-DE", "fr")
* @returns The matching identity generator language code or null if no match
*
* @example
* mapUiLanguageToIdentityLanguage("en-US") // returns "en"
* mapUiLanguageToIdentityLanguage("nl") // returns "nl"
* mapUiLanguageToIdentityLanguage("de-CH") // returns "de"
* mapUiLanguageToIdentityLanguage("fr") // returns null (no French identity generator)
*/
declare function mapUiLanguageToIdentityLanguage(uiLanguageCode: string | null | undefined): string | null;
/**
* Creates a new identity generator based on the language.
@@ -265,4 +285,4 @@ declare const CreateIdentityGenerator: (language: string) => IdentityGenerator;
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages };
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type IAgeRangeOption, type IBirthdateOptions, type IDecadeFirstnames, type IIdentityGenerator, type ILanguageOption, type Identity, IdentityGenerator, IdentityGeneratorDe, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator, convertAgeRangeToBirthdateOptions, getAvailableAgeRanges, getAvailableLanguages, mapUiLanguageToIdentityLanguage };
@@ -34,7 +34,8 @@ __export(index_exports, {
UsernameEmailGenerator: () => UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions: () => convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges: () => getAvailableAgeRanges,
getAvailableLanguages: () => getAvailableLanguages
getAvailableLanguages: () => getAvailableLanguages,
mapUiLanguageToIdentityLanguage: () => mapUiLanguageToIdentityLanguage
});
module.exports = __toCommonJS(index_exports);
@@ -5926,11 +5927,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5964,5 +6003,6 @@ var CreateUsernameEmailGenerator = () => {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
});
@@ -5890,11 +5890,49 @@ function convertAgeRangeToBirthdateOptions(ageRange) {
// src/utils/LanguageProvider.ts
function getAvailableLanguages() {
return [
{ value: "en", label: "English", flag: "\u{1F1EC}\u{1F1E7}" },
{ value: "nl", label: "Nederlands", flag: "\u{1F1F3}\u{1F1F1}" },
{ value: "de", label: "Deutsch", flag: "\u{1F1E9}\u{1F1EA}" }
{
value: "en",
label: "English",
flag: "\u{1F1EC}\u{1F1E7}",
alternativeCodes: ["en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-IE", "en-ZA", "en-SG", "en-IN"]
},
{
value: "nl",
label: "Nederlands",
flag: "\u{1F1F3}\u{1F1F1}",
alternativeCodes: ["nl-NL", "nl-BE"]
},
{
value: "de",
label: "Deutsch",
flag: "\u{1F1E9}\u{1F1EA}",
alternativeCodes: ["de-DE", "de-AT", "de-CH", "de-LU", "de-LI"]
}
];
}
function mapUiLanguageToIdentityLanguage(uiLanguageCode) {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
const exactMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
const alternativeMatch = availableLanguages.find(
(lang) => lang.alternativeCodes?.some((code) => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
const baseCode = normalizedCode.split("-")[0];
const baseMatch = availableLanguages.find((lang) => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
return null;
}
// src/factories/IdentityGeneratorFactory.ts
var CreateIdentityGenerator = (language) => {
@@ -5927,5 +5965,6 @@ export {
UsernameEmailGenerator,
convertAgeRangeToBirthdateOptions,
getAvailableAgeRanges,
getAvailableLanguages
getAvailableLanguages,
mapUiLanguageToIdentityLanguage
};
@@ -0,0 +1,88 @@
import { describe, it, expect } from 'vitest';
import { getAvailableLanguages, mapUiLanguageToIdentityLanguage } from '../utils/LanguageProvider';
describe('LanguageProvider', () => {
describe('getAvailableLanguages', () => {
it('should return a list of available languages', () => {
const languages = getAvailableLanguages();
expect(languages).toBeDefined();
expect(languages.length).toBeGreaterThan(0);
expect(languages[0]).toHaveProperty('value');
expect(languages[0]).toHaveProperty('label');
expect(languages[0]).toHaveProperty('flag');
});
});
describe('mapUiLanguageToIdentityLanguage', () => {
describe('Dutch mappings', () => {
it('should map "nl" to "nl"', () => {
expect(mapUiLanguageToIdentityLanguage('nl')).toBe('nl');
});
it('should map "nl-NL" to "nl"', () => {
expect(mapUiLanguageToIdentityLanguage('nl-NL')).toBe('nl');
});
it('should map "nl-BE" to "nl" (Belgian Dutch)', () => {
expect(mapUiLanguageToIdentityLanguage('nl-BE')).toBe('nl');
});
it('should be case-insensitive for "NL"', () => {
expect(mapUiLanguageToIdentityLanguage('NL')).toBe('nl');
});
it('should be case-insensitive for "NL-NL"', () => {
expect(mapUiLanguageToIdentityLanguage('NL-NL')).toBe('nl');
});
it('should be case-insensitive for "NL-BE"', () => {
expect(mapUiLanguageToIdentityLanguage('NL-BE')).toBe('nl');
});
});
describe('Edge cases', () => {
it('should return null for null input', () => {
expect(mapUiLanguageToIdentityLanguage(null)).toBe(null);
});
it('should return null for undefined input', () => {
expect(mapUiLanguageToIdentityLanguage(undefined)).toBe(null);
});
it('should return null for empty string', () => {
expect(mapUiLanguageToIdentityLanguage('')).toBe(null);
});
it('should return null for whitespace', () => {
expect(mapUiLanguageToIdentityLanguage(' ')).toBe(null);
});
it('should return null for invalid format', () => {
expect(mapUiLanguageToIdentityLanguage('invalid')).toBe(null);
});
it('should return null for numbers', () => {
expect(mapUiLanguageToIdentityLanguage('123')).toBe(null);
});
});
describe('Mixed case and locale variants', () => {
it('should handle mixed case "En-Us"', () => {
expect(mapUiLanguageToIdentityLanguage('En-Us')).toBe('en');
});
it('should handle mixed case "nL-Nl"', () => {
expect(mapUiLanguageToIdentityLanguage('nL-Nl')).toBe('nl');
});
it('should extract base language from unknown locale "en-ZZ"', () => {
expect(mapUiLanguageToIdentityLanguage('en-ZZ')).toBe('en');
});
it('should extract base language from unknown locale "nl-ZZ"', () => {
expect(mapUiLanguageToIdentityLanguage('nl-ZZ')).toBe('nl');
});
});
});
});
@@ -16,6 +16,13 @@ export interface ILanguageOption {
* The flag emoji for the language (e.g., "🇬🇧", "🇳🇱", "🇩🇪")
*/
flag: string;
/**
* Alternative language codes that map to this identity generator language.
* Used for matching UI locale codes to identity generator languages.
* For example, "en-US", "en-GB", "en-CA" all map to "en"
*/
alternativeCodes?: string[];
}
/**
@@ -25,8 +32,69 @@ export interface ILanguageOption {
*/
export function getAvailableLanguages(): ILanguageOption[] {
return [
{ value: 'en', label: 'English', flag: '🇬🇧' },
{ value: 'nl', label: 'Nederlands', flag: '🇳🇱' },
{ value: 'de', label: 'Deutsch', flag: '🇩🇪' }
{
value: 'en',
label: 'English',
flag: '🇬🇧',
alternativeCodes: ['en-US', 'en-GB', 'en-CA', 'en-AU', 'en-NZ', 'en-IE', 'en-ZA', 'en-SG', 'en-IN']
},
{
value: 'nl',
label: 'Nederlands',
flag: '🇳🇱',
alternativeCodes: ['nl-NL', 'nl-BE']
},
{
value: 'de',
label: 'Deutsch',
flag: '🇩🇪',
alternativeCodes: ['de-DE', 'de-AT', 'de-CH', 'de-LU', 'de-LI']
}
];
}
/**
* Maps a UI language code to an identity generator language code.
* If no explicit match is found, returns null to indicate no preference.
*
* @param uiLanguageCode - The UI language code (e.g., "en", "en-US", "nl-NL", "de-DE", "fr")
* @returns The matching identity generator language code or null if no match
*
* @example
* mapUiLanguageToIdentityLanguage("en-US") // returns "en"
* mapUiLanguageToIdentityLanguage("nl") // returns "nl"
* mapUiLanguageToIdentityLanguage("de-CH") // returns "de"
* mapUiLanguageToIdentityLanguage("fr") // returns null (no French identity generator)
*/
export function mapUiLanguageToIdentityLanguage(uiLanguageCode: string | null | undefined): string | null {
if (!uiLanguageCode) {
return null;
}
const normalizedCode = uiLanguageCode.toLowerCase();
const availableLanguages = getAvailableLanguages();
// First, try exact match with the primary value
const exactMatch = availableLanguages.find(lang => lang.value.toLowerCase() === normalizedCode);
if (exactMatch) {
return exactMatch.value;
}
// Then, try matching with alternative codes
const alternativeMatch = availableLanguages.find(lang =>
lang.alternativeCodes?.some(code => code.toLowerCase() === normalizedCode)
);
if (alternativeMatch) {
return alternativeMatch.value;
}
// Finally, try matching the base language code (e.g., "en" from "en-US")
const baseCode = normalizedCode.split('-')[0];
const baseMatch = availableLanguages.find(lang => lang.value.toLowerCase() === baseCode);
if (baseMatch) {
return baseMatch.value;
}
// No match found
return null;
}