feat: support author sorting (last name first), closes #1799 (#1865)

* [Issue #1799](https://github.com/readest/readest/issues/1799): Changing the name order when sorting the book by Author by placing the last name first in Arabic, Tibetan, German, English, Spanish, French, Hindi, Italian, Dutch, Polish, Portuguese, Russian, Thai, Turkish and Ukrainian languages

* refactor author sort

---------

Co-authored-by: Huang Xin <chrox.huang@gmail.com>
This commit is contained in:
German Shein
2025-08-22 09:59:59 +04:00
committed by GitHub
parent d390209dab
commit 86f705eae9
2 changed files with 22 additions and 5 deletions
@@ -239,8 +239,8 @@ const Bookshelf: React.FC<BookshelfProps> = ({
const bTitle = formatTitle(b.title);
return aTitle.localeCompare(bTitle, uiLanguage || navigator.language);
case 'author':
const aAuthors = formatAuthors(a.author);
const bAuthors = formatAuthors(b.author);
const aAuthors = formatAuthors(a.author, a?.primaryLanguage || 'en', true);
const bAuthors = formatAuthors(b.author, b?.primaryLanguage || 'en', true);
return aAuthors.localeCompare(bAuthors, uiLanguage || navigator.language);
case 'updated':
return new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
+20 -3
View File
@@ -91,21 +91,38 @@ export const flattenContributors = (
: formatLanguageMap(contributors?.name);
};
// prettier-ignore
const LASTNAME_AUTHOR_SORT_LANGS = [ 'ar', 'bo', 'de', 'en', 'es', 'fr', 'hi', 'it', 'nl', 'pl', 'pt', 'ru', 'th', 'tr', 'uk' ];
const formatAuthorName = (name: string, lastNameFirst: boolean) => {
if (!name) return '';
const parts = name.split(' ');
if (lastNameFirst && parts.length > 1) {
return `${parts[parts.length - 1]}, ${parts.slice(0, -1).join(' ')}`;
}
return name;
};
export const formatAuthors = (
contributors: string | string[] | Contributor | Contributor[],
bookLang?: string | string[],
sortAs?: boolean,
) => {
const langCode = getBookLangCode(bookLang) || 'en';
const lastNameFirst = !!sortAs && LASTNAME_AUTHOR_SORT_LANGS.includes(langCode);
return Array.isArray(contributors)
? listFormater(langCode === 'zh', langCode).format(
contributors.map((contributor) =>
typeof contributor === 'string' ? contributor : formatLanguageMap(contributor?.name),
typeof contributor === 'string'
? formatAuthorName(contributor, lastNameFirst)
: formatAuthorName(formatLanguageMap(contributor?.name), lastNameFirst),
),
)
: typeof contributors === 'string'
? contributors
: formatLanguageMap(contributors?.name);
? formatAuthorName(contributors, lastNameFirst)
: formatAuthorName(formatLanguageMap(contributors?.name), lastNameFirst);
};
export const formatTitle = (title: string | LanguageMap) => {
return typeof title === 'string' ? title : formatLanguageMap(title);
};