mirror of
https://github.com/zen-browser/www.git
synced 2025-07-07 17:05:32 +02:00
feat(i18n): implement internationalization support and refactor components for localization
- Added i18n configuration to `astro.config.mjs` for managing locales. - Introduced utility functions for locale handling in `i18n.ts`. - Updated various components (e.g., `BackButton`, `Button`, `Community`, `Footer`, `Hero`, `NavBar`, etc.) to utilize localized strings. - Created new localized pages for `about`, `donate`, `download`, `release-notes`, and others. - Removed outdated pages and adjusted imports to reflect new structure. - Enhanced the `ModsList` component to support localization. - Added English language JSON file for translations. - Improved overall code organization and structure for better maintainability.
This commit is contained in:
parent
904d921c09
commit
54dfef1eac
36 changed files with 1481 additions and 844 deletions
|
@ -1,8 +1,9 @@
|
|||
import { useState, useEffect } from 'preact/hooks'
|
||||
import type { ZenTheme } from '../mods'
|
||||
import type { ZenTheme } from '@/mods'
|
||||
import { library, icon } from '@fortawesome/fontawesome-svg-core'
|
||||
import { faSort, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons'
|
||||
import { useModsSearch } from '../hooks/useModsSearch'
|
||||
import { useModsSearch } from '@/hooks/useModsSearch'
|
||||
import { getUI, type Locale } from '@/utils/i18n'
|
||||
|
||||
// Add icons to the library
|
||||
library.add(faSort, faSortUp, faSortDown)
|
||||
|
@ -13,10 +14,11 @@ const ascSortIcon = icon({ prefix: 'fas', iconName: 'sort-up' })
|
|||
const descSortIcon = icon({ prefix: 'fas', iconName: 'sort-down' })
|
||||
|
||||
interface ModsListProps {
|
||||
mods: ZenTheme[]
|
||||
allMods: ZenTheme[]
|
||||
locale: Locale
|
||||
}
|
||||
|
||||
export default function ModsList({ mods }: ModsListProps) {
|
||||
export default function ModsList({ allMods, locale }: ModsListProps) {
|
||||
const {
|
||||
search,
|
||||
createdSort,
|
||||
|
@ -32,7 +34,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
setLimit,
|
||||
mods: paginatedMods,
|
||||
searchParams,
|
||||
} = useModsSearch(mods)
|
||||
} = useModsSearch(allMods)
|
||||
|
||||
const [pageInput, setPageInput] = useState(page.toString())
|
||||
|
||||
|
@ -78,6 +80,8 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
window.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
const { routes: { mods } } = getUI(locale)
|
||||
|
||||
function renderPagination() {
|
||||
if (totalPages <= 1) return null
|
||||
return (
|
||||
|
@ -94,17 +98,26 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
<
|
||||
</button>
|
||||
<form onSubmit={handlePageSubmit} className="flex items-center gap-2">
|
||||
<span className="text-sm">Page</span>
|
||||
<input
|
||||
type="text"
|
||||
value={pageInput}
|
||||
onInput={handlePageInputChange}
|
||||
className="w-16 rounded border border-dark bg-transparent px-2 py-1 text-center text-sm"
|
||||
aria-label="Page number"
|
||||
/>
|
||||
<span className="text-sm">
|
||||
of {totalPages} ({totalItems} items)
|
||||
</span>
|
||||
{
|
||||
mods.pagination.pagination.split('{input}').map((value, index) => {
|
||||
if (index === 0) {
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={pageInput}
|
||||
onInput={handlePageInputChange}
|
||||
className="w-16 rounded border border-dark bg-transparent px-2 py-1 text-center text-sm"
|
||||
aria-label="Page number"
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<span className="text-sm">
|
||||
{value.replace('{totalPages}', totalPages.toString()).replace('{totalItems}', totalItems.toString())}
|
||||
</span>
|
||||
)
|
||||
})
|
||||
}
|
||||
</form>
|
||||
<button
|
||||
type="button"
|
||||
|
@ -129,7 +142,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
type="text"
|
||||
id="search"
|
||||
className="w-full rounded-full border-2 border-dark bg-transparent px-6 py-2 text-lg outline-none"
|
||||
placeholder="Type to search..."
|
||||
placeholder={mods.search}
|
||||
value={search}
|
||||
onInput={handleSearch}
|
||||
/>
|
||||
|
@ -142,7 +155,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
onClick={toggleCreatedSort}
|
||||
className="text-md flex items-center gap-2 px-4 py-2 font-semibold"
|
||||
>
|
||||
Last created
|
||||
{mods.sort.lastCreated}
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: getSortIcon(createdSort).html[0],
|
||||
|
@ -157,7 +170,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
onClick={toggleUpdatedSort}
|
||||
className="text-md flex items-center gap-2 px-4 py-2 font-semibold"
|
||||
>
|
||||
Last updated
|
||||
{mods.sort.lastUpdated}
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: getSortIcon(updatedSort).html[0],
|
||||
|
@ -168,7 +181,7 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
|
||||
<div className="flex items-center gap-2 px-4 py-2">
|
||||
<label htmlFor="limit" className="text-md font-semibold">
|
||||
Per page:
|
||||
{mods.sort.perPage}
|
||||
</label>
|
||||
<select
|
||||
id="limit"
|
||||
|
@ -214,9 +227,9 @@ export default function ModsList({ mods }: ModsListProps) {
|
|||
))
|
||||
) : (
|
||||
<div className="col-span-4 grid place-items-center gap-4 place-self-center px-8 text-center">
|
||||
<h2 className="text-lg font-bold">No results found</h2>
|
||||
<h2 className="text-lg font-bold">{mods.noResults}</h2>
|
||||
<p className="text-sm font-thin">
|
||||
Try searching for a different term or check back later.
|
||||
{mods.noResultsDescription}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue