Files
2026-10-07 20:27:06 +02:00

424 lines
20 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================================
PAGE COPY - Knowledge and Impact + News
----------------------------------------------------------------------------
Section headings, intros and empty-state messages for the three sections
this file set owns. The EN and AR strings are taken verbatim from
docs/SHARPER_Website_Draft_Section_EN_AR.docx (§5 News and Updates,
§6 Resources and Publications, §7 Knowledge Hub); the empty-state wording is
the only addition, because the draft has no copy for "the CMS is empty".
This is page prose, not UI chrome, which is why it lives beside the routes
instead of in ~/i18n/messages - the catalogue holds labels the whole site
shares. Everything a reader could otherwise mistake for content - counts,
figures, author names, dates - comes from Strapi, never from here: the draft
marks its own numbers "TBD" and says they must not be published unconfirmed.
========================================================================= */
import type { Locale } from "~/i18n";
export interface SectionCopy {
/** H1 of the section. */
readonly heading: string;
/** The standfirst under the H1. */
readonly intro: string;
/** Shown when the section has no entries at all yet. */
readonly emptyTitle: string;
readonly emptyBody: string;
/** `<meta name="description">` for the listing. */
readonly metaDescription: string;
}
type Localised<T> = Readonly<Record<Locale, T>>;
/* ---------------------------------------------------------------------------
§6 RESOURCES AND PUBLICATIONS
------------------------------------------------------------------------ */
export const RESOURCES_COPY: Localised<SectionCopy> = {
en: {
heading: "Reports, Research, and Publications",
intro:
"Explore SHARP-ER publications and practical resources for civil society organisations, communities, public institutions, researchers, and practitioners. This library provides accessible training guides, dialogue reports, policy briefs, and community awareness materials designed to be used in your own work.",
emptyTitle: "No publications have been added yet.",
emptyBody:
"Reports, research and official documents will appear here as they are published.",
metaDescription:
"Findings, articles and official documents produced through SHARP-ER’s research and dialogue work. Filter by topic, date, author and partner organisation.",
},
ar: {
heading: "تقارير وأبحاث ومنشورات",
intro:
"اكتشفوا منشورات وموارد شارب-إي آر (SHARP-ER) العملية الموجهة إلى منظمات المجتمع المدني، والمجتمعات المحلية، والمؤسسات العامة، والباحثين والممارسين. توفر هذه المكتبة أدلة تدريبية، وتقارير حوارية، وموجزات سياسات، ومواد توعوية يسهل الوصول إليها واستخدامها في عملكم اليومي.",
emptyTitle: "لم تُضف أي منشورات بعد.",
emptyBody: "ستظهر هنا التقارير والأبحاث والوثائق الرسمية فور نشرها.",
metaDescription:
"نتائج ومقالات ووثائق رسمية صادرة عن أعمال البحث والحوار في مشروع SHARP-ER، مع إمكانية التصفية حسب الموضوع والتاريخ والكاتب والمنظمة الشريكة.",
},
};
/* ---------------------------------------------------------------------------
§7 KNOWLEDGE HUB
------------------------------------------------------------------------ */
export const KNOWLEDGE_COPY: Localised<SectionCopy> = {
en: {
heading: "Learn From the SHARP Network",
intro:
"The SHARP-ER Knowledge Hub is a space for learning, evidence, and exchange. It brings together insights from dialogue, research, training, and local initiatives to help you understand what works and why. Use the Hub to find practical tools, compare regional experiences, and inform policy. Contributions from civil society, researchers, and participants are always welcome as this space grows.",
emptyTitle: "The knowledge hub is being prepared.",
emptyBody:
"Training modules, dialogue guides, case studies and FAQs will appear here as they are published.",
metaDescription:
"Training modules and toolkits, Civil Society Law Session guides, case studies and plain-language FAQs from across the SHARP network.",
},
ar: {
heading: "تعلّم من شبكة SHARP",
intro:
"يمثل مركز المعرفة لبرنامج شارب-إي آر (SHARP-ER) مساحة للتعلم وتبادل الأدلة والخبرات. يجمع المركز الرؤى المستخلصة من الحوارات والبحوث والتدريبات والمبادرات المحلية لمساعدتكم على فهم ما ينجح ولماذا. استخدموا المركز للوصول إلى أدوات عملية، ومقارنة التجارب الإقليمية، والاستفادة من الأدلة في تطوير السياسات. نرحب دائماً بمساهمات المجتمع المدني والباحثين والمشاركين مع استمرار توسع هذا الفضاء.",
emptyTitle: "يجري تجهيز مركز المعرفة.",
emptyBody:
"ستظهر هنا الوحدات التدريبية وأدلة الحوار ودراسات الحالة والأسئلة الشائعة فور نشرها.",
metaDescription:
"وحدات تدريبية وأدلة عملية، وأدلة جلسات قانون المجتمع المدني، ودراسات حالة، وأسئلة شائعة بلغة مبسّطة من شبكة SHARP.",
},
};
/**
* The five kinds of material the hub carries - the values are the
* `knowledge-item.itemType` enumeration in the CMS, verbatim.
*
* The LABELS live here rather than in ~/i18n because the CMS enumeration is
* the source of truth and it keeps training modules and toolkits apart, so
* each of the five needs its own distinct label - a filter cannot offer two
* options reading the same. The wording is the draft's own.
*/
export const KNOWLEDGE_TYPE_LABELS: Localised<Readonly<Record<string, string>>> = {
en: {
"training-module": "Training modules",
toolkit: "Toolkits",
"law-session-guide": "Civil Society Law Session guides",
"case-study": "Case studies",
faq: "FAQs",
},
ar: {
"training-module": "وحدات تدريبية",
toolkit: "أدلة عملية",
"law-session-guide": "أدلة جلسات قانون المجتمع المدني",
"case-study": "دراسات حالة",
faq: "الأسئلة الشائعة",
},
};
/** The one-line description that sits under each type. */
export const KNOWLEDGE_TYPE_BLURBS: Localised<Readonly<Record<string, string>>> = {
en: {
"training-module": "From peer-to-peer learning and dialogue-facilitation training.",
toolkit: "Practical materials civil society organisations can put to work directly.",
"law-session-guide": "From joint sessions with the Commission on Civil Society (CCS).",
"case-study": "From CSO sub-projects across the network.",
faq: "Plain-language answers on rule of law, governance, and civic participation basics.",
},
ar: {
"training-module": "من التعلّم بين الأقران وتدريب تيسير الحوار.",
toolkit: "مواد عملية يمكن لمنظمات المجتمع المدني استخدامها مباشرة.",
"law-session-guide": "من الجلسات المشتركة مع لجنة المجتمع المدني (CCS).",
"case-study": "من المشاريع الفرعية لمنظمات المجتمع المدني عبر الشبكة.",
faq: "إجابات بلغة مبسّطة حول أساسيات سيادة القانون والحوكمة والمشاركة المدنية.",
},
};
/* ---------------------------------------------------------------------------
§5 NEWS AND UPDATES
------------------------------------------------------------------------ */
export interface NewsCopy extends SectionCopy {
/** Description of the "SHARP-ER News" tab. */
readonly projectBlurb: string;
/** Description of the "From the Network" tab. */
readonly networkBlurb: string;
}
export const NEWS_COPY: Localised<NewsCopy> = {
en: {
heading: "News from SHARP-ER and the Network",
intro:
"Follow the latest SHARP-ER milestones, partner stories, and community-led initiatives. Discover how ideas move from discussion to action: whether it’s a new partnership, a local concern brought to the table, or a locally led solution.",
projectBlurb:
"Official updates on milestones, campaign launches, publications, and events.",
networkBlurb:
"Updates submitted by CSOs granted as part of the consortium, each card crediting the organisation.",
emptyTitle: "There are no updates to show yet.",
emptyBody:
"News from the project team and from the SHARP network will appear here.",
metaDescription:
"Milestones from the SHARP-ER project team, and updates from the civil society organisations we work with across Libya.",
},
ar: {
heading: "أخبار من SHARP-ER ومن الشبكة",
intro:
"تابع أحدث إنجازات برنامج شارب-إي آر (SHARP-ER)، وقصص الشركاء، والمبادرات التي تقودها المجتمعات المحلية. اكتشف كيف تتحول الأفكار من مجرد نقاشات إلى واقع ملموس، سواء كان ذلك عبر شراكة جديدة، أو طرح قضية مجتمعية للنقاش، أو ابتكار حلول محلية.",
projectBlurb:
"تحديثات رسمية حول المحطات الرئيسية، وإطلاق الحملات، والمنشورات، والفعاليات.",
networkBlurb:
"مستجدات تنشرها منظمات المجتمع المدني الشريكة ضمن الائتلاف، وتُنسب كل بطاقة إلى المنظمة الناشرة.",
emptyTitle: "لا توجد مستجدات لعرضها بعد.",
emptyBody: "ستظهر هنا أخبار فريق المشروع ومستجدات شبكة SHARP.",
metaDescription:
"محطات رئيسية من فريق مشروع SHARP-ER، ومستجدات من منظمات المجتمع المدني التي نعمل معها في مختلف أنحاء ليبيا.",
},
};
/* ---------------------------------------------------------------------------
DETAIL PAGES
------------------------------------------------------------------------ */
export interface DetailCopy {
/** "Back to all publications" - the link out of a detail page. */
readonly backToListing: string;
/** Heading of the metadata block. */
readonly aboutThis: string;
readonly published: string;
readonly author: string;
readonly partner: string;
readonly topics: string;
readonly openExternal: string;
}
export const DETAIL_COPY: Localised<DetailCopy> = {
en: {
backToListing: "Back to all publications",
aboutThis: "About this publication",
published: "Published",
author: "Author",
partner: "Partner organisation",
topics: "Topics",
openExternal: "Open the document",
},
ar: {
backToListing: "العودة إلى جميع المنشورات",
aboutThis: "عن هذا المنشور",
published: "تاريخ النشر",
author: "الكاتب",
partner: "المنظمة الشريكة",
topics: "المواضيع",
openExternal: "فتح الوثيقة",
},
};
export const KNOWLEDGE_DETAIL_COPY: Localised<Pick<DetailCopy, "backToListing" | "aboutThis">> =
{
en: {
backToListing: "Back to the knowledge hub",
aboutThis: "About this material",
},
ar: {
backToListing: "العودة إلى مركز المعرفة",
aboutThis: "عن هذه المادة",
},
};
export const NEWS_DETAIL_COPY: Localised<Pick<DetailCopy, "backToListing" | "aboutThis">> = {
en: {
backToListing: "Back to all news",
aboutThis: "About this update",
},
ar: {
backToListing: "العودة إلى جميع الأخبار",
aboutThis: "عن هذا المستجد",
},
};
/* ---------------------------------------------------------------------------
LISTING CHROME - the redesign's page furniture
----------------------------------------------------------------------------
The strings the six listing pages gained with the 2026 redesign drafts:
hero eyebrows, the pill and facet labels, the calendar's view switch, the
knowledge hub's FAQ band and its repository callout.
EVERYTHING HERE IS FURNITURE, NOT CONTENT. Not one figure, date, name or
commitment from the drafts is carried over: the drafts' sample entries,
their "12 modules", their "Closes 15 August 2026", their "within four
weeks" and their TBD counters are all absent by design (CLAUDE.md rule 5).
The two places where a draft's sentence IS reproduced are traceable to an
approved source and noted inline.
`ListingChrome` is derived from the English object, so a key added on one
side and forgotten on the other is a compile error, not a blank label.
------------------------------------------------------------------------ */
const LISTING_CHROME_EN = {
news: {
/** Draft eyebrow over the §5 headline. */
eyebrow: "Newsroom",
/** The draft's lead card reads "Read the full update". */
readFull: "Read the full update",
/** Visually hidden heading over the lead article. */
featuredLabel: "Latest update",
/** Visually hidden heading over the rest of the grid. */
moreLabel: "More updates",
},
events: {
eyebrow: "Events calendar",
/** Label of the list / month switch. */
viewLabel: "View",
viewList: "List",
viewMonth: "Month",
/** Accessible name of the month grid. */
calendarLabel: "Events by month",
previousMonth: "Previous month",
nextMonth: "Next month",
monthEmpty: "No events are scheduled in this month.",
/** Announced before the day number of a cell that carries events. */
dayLabel: "Events on {date}",
},
applications: {
eyebrow: "Applications and opportunities",
/**
* The draft's three-step application form IS built (see
* ../applications-and-opportunities.tsx), but its attachment limit, its
* reference number and its "within four weeks" are not: none of the three
* is true of this project, so the page states none of them. The wording
* that replaced them lives in ../_events-opportunities/copy.ts under
* `apply`, annotated key by key.
*/
pathwayAllLabel: "Ways to take part",
},
resources: {
eyebrow: "Resources and publications",
/** Accessible name of the filter sidebar. */
facetsLabel: "Refine these results",
searchPlaceholder: "Title, author, keyword",
/** `resource.resourceLanguage`, spelled out for the card's language chip. */
languageEn: "English",
languageAr: "Arabic",
languageBilingual: "English and Arabic",
},
knowledge: {
eyebrow: "Knowledge hub",
searchPlaceholder: "Search the hub — topic, module, or keyword",
/**
* The count under a type card. The number always comes from Strapi, and
* the line is dropped entirely at zero rather than reading "0 published".
*/
itemCount: "{count} published",
browseLabel: "Browse by type",
faqEyebrow: "Plain-language basics",
faqHeading: "Frequently asked questions",
/** Expanded from the approved §7 line for the FAQ entry of the hub. */
faqIntro:
"Plain-language answers on rule of law, governance, and civic participation basics.",
faqEmpty: "Answers are being prepared and will appear here.",
repositoryEyebrow: "Long-term repository",
/**
* ToR §2 and §3.3: the site "acts as a long-term repository for knowledge
* and resource sharing linked to SHARP-ER activities and outputs" "with
* version control, DOI/handle readiness, and searchable metadata". The
* draft's stronger claim - that every item already is versioned and kept
* beyond the project's end - is not made here.
*/
repositoryHeadline:
"A long-term repository for knowledge and resources linked to SHARP-ER activities and outputs, with version control and searchable metadata.",
repositoryAction: "Browse publications",
},
activities: {
partnerFilterLabel: "Filter by partner",
allPartners: "All partners",
/** Visually hidden heading over the two onward cards. */
nextStepsLabel: "Where to go next",
nextEventsEyebrow: "Next",
nextApplicationsEyebrow: "Get involved",
},
} as const;
export type ListingChrome = {
readonly [Section in keyof typeof LISTING_CHROME_EN]: {
readonly [Key in keyof (typeof LISTING_CHROME_EN)[Section]]: string;
};
};
const LISTING_CHROME_AR: ListingChrome = {
news: {
eyebrow: "غرفة الأخبار",
readFull: "اقرأ المستجد كاملًا",
featuredLabel: "أحدث مستجد",
moreLabel: "مستجدات أخرى",
},
events: {
eyebrow: "التقويم الزمني للفعاليات",
viewLabel: "طريقة العرض",
viewList: "قائمة",
viewMonth: "شهر",
calendarLabel: "الفعاليات حسب الشهر",
previousMonth: "الشهر السابق",
nextMonth: "الشهر التالي",
monthEmpty: "لا توجد فعاليات مجدولة في هذا الشهر.",
dayLabel: "فعاليات يوم {date}",
},
applications: {
eyebrow: "طلبات وفرص المشاركة",
pathwayAllLabel: "طرق المشاركة",
},
resources: {
eyebrow: "الموارد والمنشورات",
facetsLabel: "تصفية النتائج",
searchPlaceholder: "العنوان أو الكاتب أو كلمة مفتاحية",
languageEn: "الإنجليزية",
languageAr: "العربية",
languageBilingual: "الإنجليزية والعربية",
},
knowledge: {
eyebrow: "مركز المعرفة",
searchPlaceholder: "ابحث في المركز: موضوع أو وحدة أو كلمة مفتاحية",
itemCount: "عدد المواد: {count}",
browseLabel: "التصفح حسب النوع",
faqEyebrow: "أساسيات بلغة مبسّطة",
faqHeading: "الأسئلة الشائعة",
faqIntro:
"إجابات بلغة مبسّطة حول أساسيات سيادة القانون والحوكمة والمشاركة المدنية.",
faqEmpty: "يجري إعداد الإجابات وستظهر هنا.",
repositoryEyebrow: "مستودع طويل الأمد",
repositoryHeadline:
"مستودع طويل الأمد للمعرفة والموارد المرتبطة بأنشطة SHARP-ER ومخرجاته، مع ضبط الإصدارات وبيانات وصفية قابلة للبحث.",
repositoryAction: "تصفّح المنشورات",
},
activities: {
partnerFilterLabel: "التصفية حسب الشريك",
allPartners: "جميع الشركاء",
nextStepsLabel: "إلى أين بعد ذلك",
nextEventsEyebrow: "التالي",
nextApplicationsEyebrow: "شارك معنا",
},
};
const LISTING_CHROME: Localised<ListingChrome> = {
en: LISTING_CHROME_EN,
ar: LISTING_CHROME_AR,
};
/** The listing chrome for a locale. Never returns "". */
export function getListingChrome(locale: Locale): ListingChrome {
return LISTING_CHROME[locale] ?? LISTING_CHROME_EN;
}
/**
* `resource.resourceLanguage` spelled out. Returns undefined for a value the
* enumeration does not carry, so the chip is dropped rather than invented.
*/
export function resourceLanguageLabel(
value: string | null | undefined,
locale: Locale,
): string | undefined {
const copy = getListingChrome(locale).resources;
switch (value) {
case "en":
return copy.languageEn;
case "ar":
return copy.languageAr;
case "bilingual":
return copy.languageBilingual;
default:
return undefined;
}
}