Compare commits
3 commits
8148d2c954
...
d53039c75d
| Author | SHA1 | Date | |
|---|---|---|---|
| d53039c75d | |||
| 6df73851e5 | |||
| 484c942541 |
11 changed files with 60 additions and 32 deletions
|
|
@ -1,12 +1,19 @@
|
|||
---
|
||||
// DarkModeToggle component - cycles between auto / light / dark
|
||||
import { getLocaleFromUrl, t } from "../utils/i18n";
|
||||
|
||||
const currentLang = getLocaleFromUrl(Astro.url);
|
||||
---
|
||||
|
||||
<button
|
||||
id="darkModeToggle"
|
||||
type="button"
|
||||
class="flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer text-neutral-600 dark:text-neutral-300 hover:text-neutral-900 dark:hover:text-white hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors"
|
||||
aria-label="Changer le thème"
|
||||
aria-label={t('ui', 'changeTheme', currentLang)}
|
||||
data-theme-labels={JSON.stringify({
|
||||
auto: t('ui', 'themeAuto', currentLang),
|
||||
light: t('ui', 'themeLight', currentLang),
|
||||
dark: t('ui', 'themeDark', currentLang),
|
||||
})}
|
||||
>
|
||||
<!-- Auto icon (system preference) -->
|
||||
<svg
|
||||
|
|
@ -81,8 +88,8 @@
|
|||
|
||||
function updateAriaLabel(preference: 'auto' | 'light' | 'dark') {
|
||||
const toggle = document.getElementById('darkModeToggle');
|
||||
const labels = { auto: 'Thème : automatique', light: 'Thème : clair', dark: 'Thème : sombre' };
|
||||
toggle?.setAttribute('aria-label', labels[preference]);
|
||||
const labels = JSON.parse(toggle?.dataset.themeLabels || '{}');
|
||||
toggle?.setAttribute('aria-label', labels[preference] || preference);
|
||||
}
|
||||
|
||||
const cycle: Record<string, 'light' | 'dark' | 'auto'> = { auto: 'light', light: 'dark', dark: 'auto' };
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
---
|
||||
import Logo from "../components/logo.astro";
|
||||
import { getLocaleFromUrl, t } from "../utils/i18n";
|
||||
|
||||
// Détection de la langue courante par le path uniquement
|
||||
const pathname = Astro.url.pathname;
|
||||
const currentLang = pathname.startsWith('/en') ? 'en' : pathname.startsWith('/ar') ? 'ar' : 'fr';
|
||||
const currentLang = getLocaleFromUrl(Astro.url);
|
||||
|
||||
// Menu localisé
|
||||
const menus = {
|
||||
|
|
@ -40,7 +39,7 @@ const currentMenus = menus[currentLang] || menus.fr;
|
|||
<button
|
||||
id="mobileMenuBackground"
|
||||
type="button"
|
||||
aria-label="Fermer le menu"
|
||||
aria-label={t('ui', 'closeMenu', currentLang)}
|
||||
class="fixed inset-0 z-20 hidden w-screen h-screen duration-300 ease-out bg-white/90 dark:bg-neutral-950/90 appearance-none border-0 p-0 cursor-default"
|
||||
>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
import HomeIcon from "./icons/HomeIcon.astro";
|
||||
import { getLocaleFromUrl, getHomePath, t } from "../utils/i18n";
|
||||
|
||||
const pathname = Astro.url.pathname;
|
||||
const currentLang = pathname.startsWith('/en') ? 'en' : pathname.startsWith('/ar') ? 'ar' : 'fr';
|
||||
const isHome = pathname === '/' || pathname === '/en' || pathname === '/en/' || pathname === '/ar' || pathname === '/ar/';
|
||||
const homeUrl = currentLang === 'en' ? '/en' : currentLang === 'ar' ? '/ar' : '/';
|
||||
const currentLang = getLocaleFromUrl(Astro.url);
|
||||
const homeUrl = getHomePath(currentLang);
|
||||
const isHome = (Astro.url.pathname.replace(/\/$/, '') || '/') === homeUrl;
|
||||
---
|
||||
|
||||
{!isHome && (
|
||||
<a
|
||||
href={homeUrl}
|
||||
class="group relative z-30 flex items-center gap-3 text-neutral-600 dark:text-neutral-300 hover:text-black dark:hover:text-white transition-colors"
|
||||
title="Accueil"
|
||||
title={t('nav', 'home', currentLang)}
|
||||
>
|
||||
<HomeIcon size={20} class="group-hover:scale-110 transition-transform duration-200" />
|
||||
<span class="font-medium text-lg tracking-wide whitespace-nowrap">Jalil Arfaoui</span>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ title: "DisMoi"
|
|||
description: "إضافة متصفّح في مجال التكنولوجيا المدنية تضيف معلومات سياقية على أي صفحة ويب."
|
||||
date: 2019-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "PHP", "Symfony"]
|
||||
url: "https://www.dismoi.io/"
|
||||
github: "https://github.com/dis-moi"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
إضافة متصفّح مفتوحة المصدر تتيح لمساهمين موثوقين (صحفيون، جمعيات، مدقّقو حقائق) إضافة معلومات سياقية مباشرة على صفحات الويب التي يزورها المستخدمون.
|
||||
إضافة متصفّح مفتوحة المصدر تضيف طبقة معلومات تعاونية على الويب. ينشر مساهمون موثوقون — صحفيون، جمعيات، مدقّقو حقائق — رسائل سياقية تظهر مباشرة على الصفحات التي يزورها المستخدمون المشتركون. متوفّرة على Chrome وFirefox وEdge وOpera. بدون إعلانات، تحترم الخصوصية، بترخيص AGPL v3.
|
||||
|
||||
مشروع شارك في تأسيسه وتطويره من 2019 إلى 2021، مدعوم من منظمات التحقق من المعلومات.
|
||||
تشمل المنصة إضافة المتصفّح (React، Redux، TypeScript)، وواجهة برمجة خلفية (Symfony، API Platform، MariaDB)، وتطبيق ويب Node.js والموقع الإلكتروني.
|
||||
|
||||
مشروع شارك في تأسيسه عام 2019.
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ title: "DisMoi"
|
|||
description: "Civic tech browser extension that adds contextual information to any web page."
|
||||
date: 2019-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "PHP", "Symfony"]
|
||||
url: "https://www.dismoi.io/"
|
||||
github: "https://github.com/dis-moi"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
Open source browser extension allowing trusted contributors (journalists, associations, fact-checkers) to add contextual information directly on web pages visited by users.
|
||||
Open source browser extension that adds a collaborative information layer on top of the web. Trusted contributors — journalists, associations, fact-checkers — publish contextual messages that appear directly on pages visited by subscribed users. Available on Chrome, Firefox, Edge and Opera. Ad-free, privacy-respecting, AGPL v3 licensed.
|
||||
|
||||
Project co-founded and developed from 2019 to 2021, supported by fact-checking organizations.
|
||||
The platform includes the browser extension (React, Redux, TypeScript), an API backend (Symfony, API Platform, MariaDB), a Node.js web application and the website.
|
||||
|
||||
Project co-founded in 2019.
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ title: "DisMoi"
|
|||
description: "Extension navigateur civic tech pour ajouter de l'information contextuelle sur n'importe quelle page web."
|
||||
date: 2019-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "PHP", "Symfony"]
|
||||
url: "https://www.dismoi.io/"
|
||||
github: "https://github.com/dis-moi"
|
||||
featured: true
|
||||
lang: "fr"
|
||||
---
|
||||
|
||||
Extension navigateur open source permettant à des contributeurs de confiance (journalistes, associations, fact-checkers) d'ajouter des informations contextuelles directement sur les pages web visitées par les utilisateurs.
|
||||
Extension navigateur open source qui ajoute une couche d'information collaborative sur le web. Des contributeurs de confiance — journalistes, associations, fact-checkers — publient des messages contextuels qui apparaissent directement sur les pages visitées par les utilisateurs abonnés. Disponible sur Chrome, Firefox, Edge et Opera. Sans publicité, respectueuse de la vie privée, sous licence AGPL v3.
|
||||
|
||||
Projet cofondé et développé de 2019 à 2021, soutenu par des organisations de vérification des faits.
|
||||
La plateforme comprend l'extension navigateur (React, Redux, TypeScript), un backend API (Symfony, API Platform, MariaDB), une application web Node.js et le site web.
|
||||
|
||||
Projet cofondé en 2019.
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ title: "mon-entreprise.urssaf.fr"
|
|||
description: "المساعد الرسمي لروّاد الأعمال في فرنسا. أكثر من 20 محاكيًا اجتماعيًا-ضريبيًا، مليون مستخدم شهريًا."
|
||||
date: 2024-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Redux", "Node.js"]
|
||||
url: "https://mon-entreprise.urssaf.fr/"
|
||||
github: "https://github.com/betagouv/mon-entreprise"
|
||||
featured: false
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
محاكيات اشتراكات اجتماعية وضرائب ومساعدات لمؤسسي الشركات. مشروع مفتوح المصدر تقوده Urssaf وbeta.gouv.fr، يستخدمه أكثر من مليون شخص شهريًا.
|
||||
خدمة رقمية عمومية طوّرتها [Urssaf](https://www.urssaf.fr/) في إطار برنامج [beta.gouv.fr](https://beta.gouv.fr/)، يستخدمها أكثر من مليون مستخدم شهريًا. يوفّر الموقع نحو عشرين محاكيًا ومساعدًا يغطّون الجوانب القانونية والضريبية والاجتماعية لحياة روّاد الأعمال: اختيار الشكل القانوني، حساب الاشتراكات، تكلفة التوظيف، مقارنة الأنظمة، الأرباح الموزّعة، التوقّف عن النشاط، الاقتصاد التشاركي...
|
||||
|
||||
يعتمد محرّك الحساب على [Publicodes](https://publi.codes/)، لغة تصريحية لنمذجة القواعد الاجتماعية-الضريبية الفرنسية.
|
||||
يعتمد محرّك الحساب جزئيًا على [Publicodes](https://publi.codes/)، لغة تصريحية مفتوحة المصدر تُنمذج القواعد الاجتماعية-الضريبية الفرنسية وتشرح كل نتيجة للمستخدم. يمكن دمج المحاكيات في مواقع أخرى عبر iframe أو واجهة برمجة REST.
|
||||
|
||||
أنا مطوّر رئيسي في الفريق منذ بداية 2024. إلى جانب البرمجة، أُرافق الفريق في ممارسات التطوير وقرارات الهندسة المعمارية وجودة البرمجيات. على صعيد التطوير، صمّمتُ محاكي الاقتصاد التشاركي (تأجير مفروش) وأُساهم في مُقارن الأشكال القانونية، وتنسيق الأسئلة في المحاكيات، ونظام التصميم…
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ title: "mon-entreprise.urssaf.fr"
|
|||
description: "The official assistant for entrepreneurs in France. Over 20 socio-fiscal simulators, one million users per month."
|
||||
date: 2024-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Redux", "Node.js"]
|
||||
url: "https://mon-entreprise.urssaf.fr/"
|
||||
github: "https://github.com/betagouv/mon-entreprise"
|
||||
featured: false
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
Social contribution, tax and startup aid simulators. Open source project led by Urssaf and beta.gouv.fr, used by over one million people every month.
|
||||
A public digital service built by [Urssaf](https://www.urssaf.fr/) as part of the [beta.gouv.fr](https://beta.gouv.fr/) program, used by over one million users every month. The site offers around twenty simulators and assistants covering the legal, tax and social aspects of entrepreneurship: choosing a legal status, calculating contributions, hiring costs, comparing schemes, dividends, business cessation, collaborative economy...
|
||||
|
||||
The calculation engine relies on [Publicodes](https://publi.codes/), a declarative language for modeling French socio-fiscal rules.
|
||||
The calculation engine partly relies on [Publicodes](https://publi.codes/), an open source declarative language that models French socio-fiscal rules and explains each result to the user. Simulators can be embedded on third-party sites via iframe or REST API.
|
||||
|
||||
I have been lead developer on the team since early 2024. Beyond code, I support the team on development practices, architecture decisions and software quality. On the development side, I designed the collaborative economy simulator (furnished rental) and I contribute to the legal status comparator, question orchestration in simulators, the design system...
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ title: "mon-entreprise.urssaf.fr"
|
|||
description: "L'assistant officiel des créateurs d'entreprise en France. Plus de 20 simulateurs socio-fiscaux, un million d'usagers par mois."
|
||||
date: 2024-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js"]
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Redux", "Node.js"]
|
||||
url: "https://mon-entreprise.urssaf.fr/"
|
||||
github: "https://github.com/betagouv/mon-entreprise"
|
||||
featured: false
|
||||
lang: "fr"
|
||||
---
|
||||
|
||||
Simulateurs de cotisations sociales, d'impôts et d'aides aux créateurs d'entreprise. Projet open source porté par l'Urssaf et beta.gouv.fr, utilisé par plus d'un million de personnes chaque mois.
|
||||
Service public numérique porté par l'[Urssaf](https://www.urssaf.fr/) dans le cadre de [beta.gouv.fr](https://beta.gouv.fr/), utilisé par plus d'un million d’usagers chaque mois. Le site propose une vingtaine de simulateurs et assistants couvrant les aspects juridiques, fiscaux et sociaux de la vie de l'entrepreneur : choix du statut, calcul de cotisations, coût d'embauche, comparaison de régimes, dividendes, cessation d'activité, économie collaborative...
|
||||
|
||||
Le moteur de calcul repose sur [Publicodes](https://publi.codes/), un langage déclaratif pour modéliser les règles socio-fiscales françaises.
|
||||
Le moteur de calcul repose en partie sur [Publicodes](https://publi.codes/), un langage déclaratif open source qui modélise les règles socio-fiscales françaises et permet d'expliquer chaque résultat à l'utilisateur. Les simulateurs sont intégrables sur des sites tiers via iframe ou API REST.
|
||||
|
||||
Je suis lead dev dans l'équipe depuis début 2024. Au-delà du code, j'accompagne l'équipe sur les pratiques de développement, les choix d'architecture et la qualité logicielle. Côté développement, j'ai notamment conçu le simulateur d'économie collaborative (location de meublé) et je contribue au comparateur de statuts juridiques, à l'orchestration des questions dans les simulateurs, au design system…
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ export const translations = {
|
|||
darkMode: { fr: 'Mode sombre', en: 'Dark mode', ar: 'الوضع الداكن' },
|
||||
lightMode: { fr: 'Mode clair', en: 'Light mode', ar: 'الوضع الفاتح' },
|
||||
},
|
||||
ui: {
|
||||
closeMenu: { fr: 'Fermer le menu', en: 'Close menu', ar: 'إغلاق القائمة' },
|
||||
changeTheme: { fr: 'Changer le thème', en: 'Change theme', ar: 'تغيير المظهر' },
|
||||
themeAuto: { fr: 'Thème : automatique', en: 'Theme: auto', ar: 'المظهر: تلقائي' },
|
||||
themeLight: { fr: 'Thème : clair', en: 'Theme: light', ar: 'المظهر: فاتح' },
|
||||
themeDark: { fr: 'Thème : sombre', en: 'Theme: dark', ar: 'المظهر: داكن' },
|
||||
},
|
||||
categories: {
|
||||
pro: { fr: 'Professionnel', en: 'Professional', ar: 'مهني' },
|
||||
comedy: { fr: 'Comédie', en: 'Comedy', ar: 'كوميديا' },
|
||||
|
|
|
|||
|
|
@ -79,6 +79,6 @@ function matchDynamicPattern(
|
|||
export function getAlternateUrls(
|
||||
pathname: string,
|
||||
): Record<Locale, string> | undefined {
|
||||
const normalized = pathname.replace(/\/$/, "") || "/";
|
||||
const normalized = decodeURIComponent(pathname.replace(/\/$/, "") || "/");
|
||||
return pathIndex.get(normalized) ?? matchDynamicPattern(normalized);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue