From 0a853082db42b4d2768908edf44c89956af246b4 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Fri, 9 May 2025 01:08:44 +0200 Subject: [PATCH] Align language sorting with mihon Always show "All" as the first language and "Other" as the last --- src/modules/core/utils/Languages.ts | 47 ++++++++++++++++++++++- src/modules/extension/Extensions.utils.ts | 9 +++-- src/modules/source/services/Sources.ts | 8 ++-- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/modules/core/utils/Languages.ts b/src/modules/core/utils/Languages.ts index 1fd38619..607fc73f 100644 --- a/src/modules/core/utils/Languages.ts +++ b/src/modules/core/utils/Languages.ts @@ -8,6 +8,7 @@ import { t } from 'i18next'; import { ISOLanguage, IsoLanguages } from '@/modules/core/IsoLanguages.ts'; +import { TranslationKey } from '@/Base.types.ts'; export enum DefaultLanguage { ALL = 'all', @@ -15,6 +16,12 @@ export enum DefaultLanguage { LOCAL_SOURCE = 'localsourcelang', } +const DEFAULT_LANGUAGE_TO_TRANSLATION: Record = { + [DefaultLanguage.ALL]: 'extension.language.all', + [DefaultLanguage.OTHER]: 'extension.language.other', + [DefaultLanguage.LOCAL_SOURCE]: 'extension.language.other', +}; + type LanguageObject = ISOLanguage & { orgCode: string; isoCode: string }; function getISOLanguage(code: string): LanguageObject | null { @@ -63,6 +70,11 @@ export function getLanguage(code: string): LanguageObject { } export function languageCodeToName(code: string): string { + const isCustomLanguage = Object.keys(DEFAULT_LANGUAGE_TO_TRANSLATION).includes(code); + if (isCustomLanguage) { + return t(DEFAULT_LANGUAGE_TO_TRANSLATION[code as DefaultLanguage]); + } + return getLanguage(code).nativeName; } @@ -93,5 +105,36 @@ export function getDefaultLanguages(): string[] { return [...defaultNativeLang(), DefaultLanguage.ALL]; } -export const languageSortComparator = (a: string, b: string) => - languageCodeToName(a).localeCompare(languageCodeToName(b)); +/** + * Sort languages by their native name. + * Custom languages are optionally treated specially: + * - All: first + * - Other: last + */ +export const languageSortComparator = (a: string, b: string, specialCustomLanguagesHandling?: boolean) => { + const isALanguageAll = a === DefaultLanguage.ALL; + const isALanguageOther = a === DefaultLanguage.OTHER || a === DefaultLanguage.LOCAL_SOURCE; + + const isBLanguageAll = b === DefaultLanguage.ALL; + const isBLanguageOther = b === DefaultLanguage.OTHER || b === DefaultLanguage.LOCAL_SOURCE; + + if (specialCustomLanguagesHandling) { + if (isALanguageAll || isBLanguageOther) { + return -1; + } + + if (isALanguageOther || isBLanguageAll) { + return 1; + } + } + + return languageCodeToName(a).localeCompare(languageCodeToName(b)); +}; + +/** + * Sort languages by their native name. + * Custom languages are treated specially: + * - All: first + * - Other: last + */ +export const languageSpecialSortComparator = (a: string, b: string) => languageSortComparator(a, b, true); diff --git a/src/modules/extension/Extensions.utils.ts b/src/modules/extension/Extensions.utils.ts index 962c175f..ecb83806 100644 --- a/src/modules/extension/Extensions.utils.ts +++ b/src/modules/extension/Extensions.utils.ts @@ -18,7 +18,7 @@ import { import { DefaultLanguage, languageCodeToName, - languageSortComparator, + languageSpecialSortComparator, toComparableLanguage, toComparableLanguages, toUniqueLanguageCodes, @@ -86,7 +86,7 @@ export function groupExtensionsByLanguage(extensions: TExtension[]): GroupedExte return 1; } - return languageSortComparator(a, b); + return languageSpecialSortComparator(a, b); }); const groupedExtensionsSortedByLanguage = extensionsBySortedLanguage.map(([language, extensionsOfLanguage]) => [ @@ -97,8 +97,9 @@ export function groupExtensionsByLanguage(extensions: TExtension[]): GroupedExte return groupedExtensionsSortedByLanguage.filter(([, extensionsOfLanguage]) => !!extensionsOfLanguage.length); } -export const getLanguagesFromExtensions = (extensions: TExtension[]): string[] => - [...new Set(extensions.map((extension) => extension.lang))].toSorted(languageSortComparator); +export const getLanguagesFromExtensions = (extensions: TExtension[]): string[] => [ + ...new Set(extensions.map((extension) => extension.lang)), +]; export const filterExtensions = ( extensions: TExtension[], diff --git a/src/modules/source/services/Sources.ts b/src/modules/source/services/Sources.ts index 53e9a003..a8dec9a4 100644 --- a/src/modules/source/services/Sources.ts +++ b/src/modules/source/services/Sources.ts @@ -15,7 +15,7 @@ import { } from '@/modules/source/Source.types.ts'; import { DefaultLanguage, - languageSortComparator, + languageSpecialSortComparator, toComparableLanguage, toComparableLanguages, toUniqueLanguageCodes, @@ -37,15 +37,15 @@ export class Sources { } static getLanguages(sources: (SourceIdInfo & SourceLanguageInfo)[]): string[] { - return [...new Set(sources.map((source) => Sources.getLanguage(source)))].toSorted(languageSortComparator); + return [...new Set(sources.map(Sources.getLanguage))]; } static groupByLanguage( sources: Source[], ): Record { - const sourcesByLanguage = Object.groupBy(sources, (source) => Sources.getLanguage(source)); + const sourcesByLanguage = Object.groupBy(sources, Sources.getLanguage); const sourcesBySortedLanguage = Object.entries(sourcesByLanguage).toSorted(([a], [b]) => - languageSortComparator(a, b), + languageSpecialSortComparator(a, b), ); const sortedSourcesBySortedLanguage = sourcesBySortedLanguage.map(([language, sourcesOfLanguage]) => [ language,