feat: homepage animations; Arabic as default locale

This commit is contained in:
2026-09-24 00:22:40 +02:00
parent 2ff5cf47cf
commit 1879a206ad
14 changed files with 268 additions and 56 deletions
+4 -4
View File
@@ -37,7 +37,7 @@ const deniedTypes = [
/**
* The locales the site ships with.
*
* `en` is the default (LTR) and `ar` is the right-to-left translation. The web
* `ar` is the default (RTL) and `en` is the left-to-right translation. The web
* app mirrors these codes in its URL prefixes (`/en/...`, `/ar/...`), so the
* codes here are part of the public contract - do not rename them.
*
@@ -47,8 +47,8 @@ const deniedTypes = [
* here plus a restart.
*/
const locales = [
{ code: 'en', name: 'English (en)', isDefault: true },
{ code: 'ar', name: 'Arabic (ar)' },
{ code: 'ar', name: 'Arabic (ar)', isDefault: true },
{ code: 'en', name: 'English (en)' },
];
const config = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Plugin => ({
@@ -59,7 +59,7 @@ const config = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Plugin =>
i18n: {
enabled: true,
config: {
defaultLocale: 'en',
defaultLocale: 'ar',
locales,
},
},
+2 -2
View File
@@ -22,8 +22,8 @@ export type LocaleDefinition = {
* is that config file.
*/
export const FALLBACK_LOCALES: LocaleDefinition[] = [
{ code: 'en', name: 'English (en)', isDefault: true },
{ code: 'ar', name: 'Arabic (ar)' },
{ code: 'ar', name: 'Arabic (ar)', isDefault: true },
{ code: 'en', name: 'English (en)' },
];
/** `type` of the users-permissions role that unauthenticated requests use. */
+1 -1
View File
@@ -247,7 +247,7 @@ async function seedDemo(
log(strapi, `${DEMO_PARTNERS.length} demo network partners`);
for (const item of DEMO_FAQS) {
await upsert(strapi, UID.faq, item, { question: { $eq: item.en.question } });
await upsert(strapi, UID.faq, item, { question: { $eq: item.ar.question } });
}
log(strapi, `${DEMO_FAQS.length} demo FAQs`);
+12 -11
View File
@@ -7,12 +7,13 @@
explicit `--demo --clean`.
THE SHAPE OF A WRITE
A seed entry is always a pair - the English document and its Arabic
A seed entry is always a pair - the Arabic document and its English
translation - because every localised content type on this site ships in
both languages (CLAUDE.md rule 7). `upsert` writes the English document
first, because that is the one carrying the identity (the slug), then
writes the Arabic locale onto the SAME document, which is how Strapi 5
models a translation: one `documentId`, one row per locale.
both languages (CLAUDE.md rule 7) and Arabic is the CMS's default locale.
`upsert` writes the Arabic document first, because that is the one
carrying the identity (the slug), then writes the English locale onto the
SAME document, which is how Strapi 5 models a translation: one
`documentId`, one row per locale.
DRAFT AND PUBLISH
Content is written as a draft and then published explicitly. Publishing
@@ -108,7 +109,7 @@ export async function upsert(
seed ends up with duplicates. */
const existing = await service.findFirst({
...(find ? { filters: find } : {}),
locale: 'en',
locale: 'ar',
...draftFilter(strapi, uid),
});
@@ -117,16 +118,16 @@ export async function upsert(
if (existing) {
documentId = existing.documentId;
await service.update({ documentId, locale: 'en', data: data.en });
await service.update({ documentId, locale: 'ar', data: data.ar });
} else {
const document = await service.create({ locale: 'en', data: data.en });
const document = await service.create({ locale: 'ar', data: data.ar });
documentId = document.documentId;
created = true;
}
/* An update against a locale the document does not have yet creates that
translation - there is no separate "add a locale" call. */
await service.update({ documentId, locale: 'ar', data: data.ar });
await service.update({ documentId, locale: 'en', data: data.en });
if (usesDraft(strapi, uid)) {
await service.publish({ documentId, locale: '*' });
@@ -144,7 +145,7 @@ export async function upsert(
* 1. `delete({ documentId })` with no locale removes the DEFAULT locale
* only, not the document. It takes `locale: '*'` to remove the lot.
* 2. `findMany({ locale })` answers for one locale, so a document whose
* English half has already gone is invisible to a search in English.
* base half has already gone is invisible to a search in that locale.
* Both locales are searched and the documentIds pooled, which also
* sweeps up orphans an earlier, less careful run left.
*/
@@ -221,7 +222,7 @@ export async function readExisting(
): Promise<SeedDocument | null> {
return documents(strapi, uid).findFirst({
...(find ? { filters: find } : {}),
locale: 'en',
locale: 'ar',
...draftFilter(strapi, uid),
populate,
});