From 1cfe0bca32083d30a3f5e558499d577959912878 Mon Sep 17 00:00:00 2001 From: Ludovic Mermod Date: Thu, 1 Feb 2024 18:26:57 +0100 Subject: [PATCH] feat: add i18n for commissions --- app/src/components/Card.tsx | 2 +- app/src/locales.ts | 27 ++++++++++-- app/src/pages/commission/[id].tsx | 44 ------------------- app/src/pages/commissions.tsx | 11 ++++- app/src/pages/news/[slug].tsx | 4 ++ app/src/types/generated/contentTypes.d.ts | 7 +++ .../content-types/commission/schema.json | 12 ++++- strapi/types/generated/contentTypes.d.ts | 8 +++- 8 files changed, 63 insertions(+), 52 deletions(-) delete mode 100644 app/src/pages/commission/[id].tsx diff --git a/app/src/components/Card.tsx b/app/src/components/Card.tsx index ee2ae3b..ff0e922 100644 --- a/app/src/components/Card.tsx +++ b/app/src/components/Card.tsx @@ -40,7 +40,7 @@ export default function Card( img = props.commission.attributes.logo; title = props.commission.attributes.name; description = props.commission.attributes.small_description; - link = `/commission/${(props.commission as any).id}`; + link = `/commission/${props.commission.attributes.slug}`; } else { img = props.img; title = props.title; diff --git a/app/src/locales.ts b/app/src/locales.ts index 84fe490..0e9da42 100644 --- a/app/src/locales.ts +++ b/app/src/locales.ts @@ -13,15 +13,23 @@ interface Translations { by: string; relatedContent: string; committee: string; + commission: string; } -const translations: { [key in Locale]: Translations } = { +type OptionsOperators = { + [key in keyof LangOptions]: (value: string) => string; +}; + +const translations: { [key in Locale]: Translations & OptionsOperators } = { en: { dateIndicator: "on", timeIndicator: "at", by: "by", relatedContent: "related content", committee: "committee", + commission: "commission", + capitalize: (s) => s.replace(/^(\s*\w)/, (s) => s.toUpperCase()), + plural: (s) => s + "s", }, fr: { dateIndicator: "le", @@ -29,20 +37,31 @@ const translations: { [key in Locale]: Translations } = { by: "par", relatedContent: "contenu lié", committee: "comité", + commission: "commission", + capitalize: (s) => s.replace(/^(\s*\w)/, (s) => s.toUpperCase()), + plural: (s) => (s.endsWith("u") ? s + "x" : s + "s"), }, }; interface LangOptions { - capitalize: boolean; + capitalize?: boolean; + plural?: boolean; } + export function applyOptions( str: string, locale: Locale, opts?: LangOptions ): string { let result = str; - if (opts?.capitalize) { - result = result.replace(/(\s*\w)/, (s) => s.toUpperCase()); + let l = translations[locale]; + + if (opts) { + Object.keys(opts).forEach((opt: string) => { + if ((opts as any)[opt] && opt in l) { + result = (l as any)[opt](result); + } + }); } return result; diff --git a/app/src/pages/commission/[id].tsx b/app/src/pages/commission/[id].tsx deleted file mode 100644 index 7527ceb..0000000 --- a/app/src/pages/commission/[id].tsx +++ /dev/null @@ -1,44 +0,0 @@ -import StrapiImage from "@/components/StrapiImage"; -import strapi from "@/strapi"; -import { ApiCommission } from "@/types/generated/contentTypes"; -import { GetServerSideProps, InferGetServerSidePropsType } from "next"; -import Markdown from "react-markdown"; - -export default function Page( - props: InferGetServerSidePropsType -) { - return ( -
-

{props.commission.attributes.name}

-

{props.commission.attributes.small_description}

- - - - {props.commission.attributes.description} - -
- ); -} - -export const getServerSideProps: GetServerSideProps<{ - commission: ApiCommission; -}> = async (context) => { - if (typeof context.params?.id !== "string") { - console.log(typeof context.params?.id); - return { notFound: true }; - } - - let commission = await strapi.findOne( - "commissions", - context.params.id, - { - populate: ["picture", "logo"], - } - ); - - return { props: { commission: commission.data } }; -}; diff --git a/app/src/pages/commissions.tsx b/app/src/pages/commissions.tsx index fad51b7..2235a2c 100644 --- a/app/src/pages/commissions.tsx +++ b/app/src/pages/commissions.tsx @@ -1,15 +1,23 @@ import Card from "@/components/Card"; +import { locale, translate } from "@/locales"; import strapi from "@/strapi"; import { ApiCommission } from "@/types/generated/contentTypes"; import { GetServerSideProps, InferGetServerSidePropsType } from "next"; +import { useRouter } from "next/router"; export default function Commissions( props: InferGetServerSidePropsType ) { + const router = useRouter(); return (
-

Commissions

+

+ {translate("commission", locale(router), { + capitalize: true, + plural: true, + })} +

{props.news.map((c) => ( @@ -24,6 +32,7 @@ export const getServerSideProps: GetServerSideProps<{ let res = await strapi.find("commissions", { sort: "name", populate: "logo", + locale: locale(context), }); return { props: { news: res.data.reverse() } }; }; diff --git a/app/src/pages/news/[slug].tsx b/app/src/pages/news/[slug].tsx index 6168385..825dfc5 100644 --- a/app/src/pages/news/[slug].tsx +++ b/app/src/pages/news/[slug].tsx @@ -62,5 +62,9 @@ export const getServerSideProps: GetServerSideProps<{ news: ApiNews }> = async ( }, }); + if (news.data.length != 1) { + return { notFound: true }; + } + return { props: { news: news.data[0] } }; }; diff --git a/app/src/types/generated/contentTypes.d.ts b/app/src/types/generated/contentTypes.d.ts index a1ee5c4..c3d5ad8 100644 --- a/app/src/types/generated/contentTypes.d.ts +++ b/app/src/types/generated/contentTypes.d.ts @@ -864,6 +864,13 @@ export interface ApiCommission extends Schema.CollectionType { localized: false; }; }>; + slug: Attribute.String & + Attribute.Required & + Attribute.SetPluginOptions<{ + i18n: { + localized: false; + }; + }>; createdAt: Attribute.DateTime; updatedAt: Attribute.DateTime; publishedAt: Attribute.DateTime; diff --git a/strapi/src/api/commission/content-types/commission/schema.json b/strapi/src/api/commission/content-types/commission/schema.json index acac2c5..72cb9e5 100644 --- a/strapi/src/api/commission/content-types/commission/schema.json +++ b/strapi/src/api/commission/content-types/commission/schema.json @@ -24,7 +24,7 @@ }, "type": "string", "required": true, - "unique": true + "unique": false }, "news": { "type": "relation", @@ -99,6 +99,16 @@ } }, "type": "text" + }, + "slug": { + "pluginOptions": { + "i18n": { + "localized": false + } + }, + "type": "string", + "required": true, + "regex": "^[a-z0-9]+(?:-[a-z0-9]+)*$" } } } diff --git a/strapi/types/generated/contentTypes.d.ts b/strapi/types/generated/contentTypes.d.ts index 91f2671..5bbc42f 100644 --- a/strapi/types/generated/contentTypes.d.ts +++ b/strapi/types/generated/contentTypes.d.ts @@ -806,7 +806,6 @@ export interface ApiCommissionCommission extends Schema.CollectionType { attributes: { name: Attribute.String & Attribute.Required & - Attribute.Unique & Attribute.SetPluginOptions<{ i18n: { localized: true; @@ -864,6 +863,13 @@ export interface ApiCommissionCommission extends Schema.CollectionType { localized: false; }; }>; + slug: Attribute.String & + Attribute.Required & + Attribute.SetPluginOptions<{ + i18n: { + localized: false; + }; + }>; createdAt: Attribute.DateTime; updatedAt: Attribute.DateTime; publishedAt: Attribute.DateTime;