From ac6fa96c9ce1a5e522199803b9edd841536a1205 Mon Sep 17 00:00:00 2001 From: Al Murad Uzzaman Date: Tue, 14 May 2024 15:34:22 +0600 Subject: [PATCH 01/23] project setup --- astro.config.mjs | 9 +- package.json | 2 +- readme.md | 2 +- src/config/config.json | 5 + src/config/menu.ar.json | 24 ++ src/config/menu.en.json | 24 ++ src/config/menu.fr.json | 24 ++ src/content/ar/about/-index.md | 9 + src/content/ar/authors/-index.md | 5 + src/content/ar/authors/john-doe.md | 20 ++ src/content/ar/authors/sam-wilson.md | 20 ++ src/content/ar/authors/william-jacob.md | 20 ++ src/content/ar/blog/-index.md | 5 + src/content/ar/blog/post-1.md | 23 ++ src/content/{ => ar}/blog/post-2.md | 0 src/content/{ => ar}/blog/post-3.md | 0 src/content/{ => ar}/blog/post-4.md | 0 src/content/{ => ar}/contact/-index.md | 0 src/content/ar/homepage/-index.md | 53 ++++ src/content/ar/pages/elements.mdx | 255 ++++++++++++++++++ src/content/ar/pages/privacy-policy.md | 30 +++ src/content/ar/sections/call-to-action.md | 10 + src/content/ar/sections/testimonial.md | 27 ++ src/content/{ => en}/about/-index.md | 0 src/content/{ => en}/authors/-index.md | 0 src/content/{ => en}/authors/john-doe.md | 0 src/content/{ => en}/authors/sam-wilson.md | 0 src/content/{ => en}/authors/william-jacob.md | 0 src/content/{ => en}/blog/-index.md | 0 src/content/{ => en}/blog/post-1.md | 0 src/content/en/blog/post-2.md | 23 ++ src/content/en/blog/post-3.md | 23 ++ src/content/en/blog/post-4.md | 23 ++ src/content/en/contact/-index.md | 6 + src/content/{ => en}/homepage/-index.md | 0 src/content/{ => en}/pages/elements.mdx | 0 src/content/{ => en}/pages/privacy-policy.md | 0 .../{ => en}/sections/call-to-action.md | 0 src/content/{ => en}/sections/testimonial.md | 0 src/content/fr/about/-index.md | 9 + src/content/fr/authors/-index.md | 5 + src/content/fr/authors/john-doe.md | 20 ++ src/content/fr/authors/sam-wilson.md | 20 ++ src/content/fr/authors/william-jacob.md | 20 ++ src/content/fr/blog/-index.md | 5 + src/content/fr/blog/post-1.md | 23 ++ src/content/fr/blog/post-2.md | 23 ++ src/content/fr/blog/post-3.md | 23 ++ src/content/fr/blog/post-4.md | 23 ++ src/content/fr/contact/-index.md | 6 + src/content/fr/homepage/-index.md | 53 ++++ src/content/fr/pages/elements.mdx | 255 ++++++++++++++++++ src/content/fr/pages/privacy-policy.md | 30 +++ src/content/fr/sections/call-to-action.md | 10 + src/content/fr/sections/testimonial.md | 27 ++ src/i18n/ar.json | 42 +++ src/i18n/en.json | 42 +++ src/i18n/fr.json | 42 +++ src/i18n/ui.ts | 63 +++++ src/layouts/Base.astro | 21 +- src/layouts/PostSingle.astro | 7 +- src/layouts/components/AuthorCard.astro | 6 +- src/layouts/components/BlogCard.astro | 18 +- src/layouts/components/Pagination.astro | 21 +- src/layouts/partials/Header.astro | 86 ++++-- src/lib/contentParser.astro | 46 +++- src/lib/taxonomyParser.astro | 19 +- src/lib/utils/i18nUtils.ts | 62 +++++ src/lib/utils/loadMenu.ts | 25 ++ src/pages/404.astro | 22 +- src/pages/{ => [...lang]}/[regular].astro | 28 +- src/pages/{ => [...lang]}/about.astro | 19 +- .../{ => [...lang]}/authors/[single].astro | 35 ++- src/pages/[...lang]/authors/index.astro | 45 ++++ src/pages/[...lang]/blog/[single].astro | 41 +++ src/pages/{ => [...lang]}/blog/index.astro | 35 ++- .../{ => [...lang]}/blog/page/[slug].astro | 76 ++++-- .../categories/[category].astro | 31 ++- .../{ => [...lang]}/categories/index.astro | 16 +- src/pages/{ => [...lang]}/contact.astro | 29 +- src/pages/{ => [...lang]}/index.astro | 43 ++- src/pages/authors/index.astro | 29 -- src/pages/blog/[single].astro | 30 --- src/pages/tags/[tag].astro | 45 ---- src/pages/tags/index.astro | 39 --- src/styles/base.scss | 2 +- 86 files changed, 1966 insertions(+), 293 deletions(-) create mode 100644 src/config/menu.ar.json create mode 100644 src/config/menu.en.json create mode 100644 src/config/menu.fr.json create mode 100644 src/content/ar/about/-index.md create mode 100644 src/content/ar/authors/-index.md create mode 100644 src/content/ar/authors/john-doe.md create mode 100644 src/content/ar/authors/sam-wilson.md create mode 100644 src/content/ar/authors/william-jacob.md create mode 100755 src/content/ar/blog/-index.md create mode 100755 src/content/ar/blog/post-1.md rename src/content/{ => ar}/blog/post-2.md (100%) rename src/content/{ => ar}/blog/post-3.md (100%) rename src/content/{ => ar}/blog/post-4.md (100%) rename src/content/{ => ar}/contact/-index.md (100%) create mode 100755 src/content/ar/homepage/-index.md create mode 100755 src/content/ar/pages/elements.mdx create mode 100644 src/content/ar/pages/privacy-policy.md create mode 100644 src/content/ar/sections/call-to-action.md create mode 100644 src/content/ar/sections/testimonial.md rename src/content/{ => en}/about/-index.md (100%) rename src/content/{ => en}/authors/-index.md (100%) rename src/content/{ => en}/authors/john-doe.md (100%) rename src/content/{ => en}/authors/sam-wilson.md (100%) rename src/content/{ => en}/authors/william-jacob.md (100%) rename src/content/{ => en}/blog/-index.md (100%) rename src/content/{ => en}/blog/post-1.md (100%) create mode 100755 src/content/en/blog/post-2.md create mode 100755 src/content/en/blog/post-3.md create mode 100755 src/content/en/blog/post-4.md create mode 100644 src/content/en/contact/-index.md rename src/content/{ => en}/homepage/-index.md (100%) rename src/content/{ => en}/pages/elements.mdx (100%) rename src/content/{ => en}/pages/privacy-policy.md (100%) rename src/content/{ => en}/sections/call-to-action.md (100%) rename src/content/{ => en}/sections/testimonial.md (100%) create mode 100644 src/content/fr/about/-index.md create mode 100644 src/content/fr/authors/-index.md create mode 100644 src/content/fr/authors/john-doe.md create mode 100644 src/content/fr/authors/sam-wilson.md create mode 100644 src/content/fr/authors/william-jacob.md create mode 100755 src/content/fr/blog/-index.md create mode 100755 src/content/fr/blog/post-1.md create mode 100755 src/content/fr/blog/post-2.md create mode 100755 src/content/fr/blog/post-3.md create mode 100755 src/content/fr/blog/post-4.md create mode 100644 src/content/fr/contact/-index.md create mode 100755 src/content/fr/homepage/-index.md create mode 100755 src/content/fr/pages/elements.mdx create mode 100644 src/content/fr/pages/privacy-policy.md create mode 100644 src/content/fr/sections/call-to-action.md create mode 100644 src/content/fr/sections/testimonial.md create mode 100644 src/i18n/ar.json create mode 100644 src/i18n/en.json create mode 100644 src/i18n/fr.json create mode 100644 src/i18n/ui.ts create mode 100644 src/lib/utils/i18nUtils.ts create mode 100644 src/lib/utils/loadMenu.ts rename src/pages/{ => [...lang]}/[regular].astro (58%) rename src/pages/{ => [...lang]}/about.astro (60%) rename src/pages/{ => [...lang]}/authors/[single].astro (68%) create mode 100755 src/pages/[...lang]/authors/index.astro create mode 100755 src/pages/[...lang]/blog/[single].astro rename src/pages/{ => [...lang]}/blog/index.astro (56%) rename src/pages/{ => [...lang]}/blog/page/[slug].astro (51%) rename src/pages/{ => [...lang]}/categories/[category].astro (62%) rename src/pages/{ => [...lang]}/categories/index.astro (63%) rename src/pages/{ => [...lang]}/contact.astro (62%) rename src/pages/{ => [...lang]}/index.astro (71%) delete mode 100755 src/pages/authors/index.astro delete mode 100755 src/pages/blog/[single].astro delete mode 100755 src/pages/tags/[tag].astro delete mode 100755 src/pages/tags/index.astro diff --git a/astro.config.mjs b/astro.config.mjs index d2c210c..78e24b3 100755 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -12,7 +12,14 @@ import config from "./src/config/config.json"; export default defineConfig({ site: config.site.base_url ? config.site.base_url : "http://examplesite.com", base: config.site.base_path ? config.site.base_path : "/", - trailingSlash: config.site.trailing_slash ? "always" : "never", + trailingSlash: config.site.trailing_slash ? "always" : "ignore", + i18n: { + locales: ["en", "fr", "ar"], + defaultLocale: "en", + routing: { + prefixDefaultLocale: false, + }, + }, image: { service: squooshImageService(), }, diff --git a/package.json b/package.json index 5f30638..e166388 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "astroplate", - "version": "3.4.5", + "version": "3.4.3", "description": "Astro and Tailwindcss boilerplate", "author": "zeon.studio", "license": "MIT", diff --git a/readme.md b/readme.md index a9badb4..d098e30 100755 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@

If you find this project useful, please give it a ⭐ to show your support.

-

👀 Demo | Page Speed (100%)🚀 +

👀 Demo | Page Speed (100%)🚀

diff --git a/src/config/config.json b/src/config/config.json index 683fe50..0e5aab5 100755 --- a/src/config/config.json +++ b/src/config/config.json @@ -12,6 +12,11 @@ "logo_text": "Astroplate" }, + "language": { + "defaultLang": "en", + "supported": ["", "en", "fr", "ar"] + }, + "settings": { "search": true, "sticky_header": true, diff --git a/src/config/menu.ar.json b/src/config/menu.ar.json new file mode 100644 index 0000000..227048e --- /dev/null +++ b/src/config/menu.ar.json @@ -0,0 +1,24 @@ +{ + "main": [ + { "name": "الرئيسية", "url": "/" }, + { "name": "نبذة عنا", "url": "/about" }, + { "name": "العناصر", "url": "/elements" }, + { + "name": "Pages", + "url": "", + "hasChildren": true, + "children": [ + { "name": "اتصل بنا", "url": "/contact" }, + { "name": "المدونة", "url": "/blog" }, + { "name": "المؤلفون", "url": "/authors" }, + { "name": "التصنيفات", "url": "/categories" }, + { "name": "العلامات", "url": "/tags" }, + { "name": "صفحة 404", "url": "/404" } + ] + } + ], + "footer": [ + { "name": "العناصر", "url": "/elements" }, + { "name": "سياسة الخصوصية", "url": "/privacy-policy" } + ] +} diff --git a/src/config/menu.en.json b/src/config/menu.en.json new file mode 100644 index 0000000..74697c8 --- /dev/null +++ b/src/config/menu.en.json @@ -0,0 +1,24 @@ +{ + "main": [ + { "name": "Home", "url": "/" }, + { "name": "About", "url": "/about" }, + { "name": "Elements", "url": "/elements" }, + { + "name": "Pages", + "url": "", + "hasChildren": true, + "children": [ + { "name": "Contact", "url": "/contact" }, + { "name": "Blog", "url": "/blog" }, + { "name": "Authors", "url": "/authors" }, + { "name": "Categories", "url": "/categories" }, + { "name": "Tags", "url": "/tags" }, + { "name": "404 Page", "url": "/404" } + ] + } + ], + "footer": [ + { "name": "Elements", "url": "/elements" }, + { "name": "Privacy Policy", "url": "/privacy-policy" } + ] +} \ No newline at end of file diff --git a/src/config/menu.fr.json b/src/config/menu.fr.json new file mode 100644 index 0000000..88b02d5 --- /dev/null +++ b/src/config/menu.fr.json @@ -0,0 +1,24 @@ +{ + "main": [ + { "name": "Accueil", "url": "/" }, + { "name": "À propos", "url": "/about" }, + { "name": "Éléments", "url": "/elements" }, + { + "name": "Pages", + "url": "", + "hasChildren": true, + "children": [ + { "name": "Contact", "url": "/contact" }, + { "name": "Blog", "url": "/blog" }, + { "name": "Auteurs", "url": "/authors" }, + { "name": "Catégories", "url": "/categories" }, + { "name": "Étiquettes", "url": "/tags" }, + { "name": "Page 404", "url": "/404" } + ] + } + ], + "footer": [ + { "name": "Éléments", "url": "/elements" }, + { "name": "Politique de confidentialité", "url": "/privacy-policy" } + ] +} \ No newline at end of file diff --git a/src/content/ar/about/-index.md b/src/content/ar/about/-index.md new file mode 100644 index 0000000..4b8e44a --- /dev/null +++ b/src/content/ar/about/-index.md @@ -0,0 +1,9 @@ +--- +title: "مهلا، أنا جون دو!" +meta_title: "About" +description: "this is meta description" +image: "/images/avatar.png" +draft: false +--- + +الشركة نفسها هي شركة ناجحة جدا. إنهم لا يعرفون فوائد الجسد، أو إلا أنهم سيحصلون عليه في أوقات أخرى، كلها، أوقات العمل، فهو يكره من هذا الوقت ولكن. يهرب من الملذات المحسوسة ليفترض أنها لا شيء، كل شيء أو، والألم هو الخيار الأكبر، فإنه أيسر عليه، وما يتبعه يقدمون الألم ونحوه! لأن وسيلة الحقيقة المذكورة تطرد اللذة وتمنع الألم، فهي تقدم كما لو \ No newline at end of file diff --git a/src/content/ar/authors/-index.md b/src/content/ar/authors/-index.md new file mode 100644 index 0000000..8d66730 --- /dev/null +++ b/src/content/ar/authors/-index.md @@ -0,0 +1,5 @@ +--- +title: "المؤلفون" +meta_title: "" +description: "this is meta description" +--- diff --git a/src/content/ar/authors/john-doe.md b/src/content/ar/authors/john-doe.md new file mode 100644 index 0000000..5f0858a --- /dev/null +++ b/src/content/ar/authors/john-doe.md @@ -0,0 +1,20 @@ +--- +title: فلان الفلاني +email: johndoe@email.com +image: "/images/avatar.png" +description: this is meta description +social: + - name: github + icon: FaGithub + link: https://github.com + + - name: twitter + icon: FaTwitter + link: https://twitter.com + + - name: linkedin + icon: FaLinkedin + link: https://linkedin.com +--- + +lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostr navigation et dolore magna aliqua. diff --git a/src/content/ar/authors/sam-wilson.md b/src/content/ar/authors/sam-wilson.md new file mode 100644 index 0000000..722db33 --- /dev/null +++ b/src/content/ar/authors/sam-wilson.md @@ -0,0 +1,20 @@ +--- +title: سام ويلسون +email: samwilson@email.com +image: "/images/avatar.png" +description: this is meta description +social: + - name: github + icon: FaGithub + link: https://github.com + + - name: twitter + icon: FaTwitter + link: https://twitter.com + + - name: linkedin + icon: FaLinkedin + link: https://linkedin.com +--- + +lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostr navigation et dolore magna aliqua. diff --git a/src/content/ar/authors/william-jacob.md b/src/content/ar/authors/william-jacob.md new file mode 100644 index 0000000..9c06b41 --- /dev/null +++ b/src/content/ar/authors/william-jacob.md @@ -0,0 +1,20 @@ +--- +title: وليام جاكوب +email: williamjacob@email.com +image: "/images/avatar.png" +description: this is meta description +social: + - name: github + icon: FaGithub + link: https://github.com + + - name: twitter + icon: FaTwitter + link: https://twitter.com + + - name: linkedin + icon: FaLinkedin + link: https://linkedin.com +--- + +lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostr navigation et dolore magna aliqua. diff --git a/src/content/ar/blog/-index.md b/src/content/ar/blog/-index.md new file mode 100755 index 0000000..e69277c --- /dev/null +++ b/src/content/ar/blog/-index.md @@ -0,0 +1,5 @@ +--- +title: "منشورات المدونة" +meta_title: "" +description: "this is meta description" +--- diff --git a/src/content/ar/blog/post-1.md b/src/content/ar/blog/post-1.md new file mode 100755 index 0000000..0246e43 --- /dev/null +++ b/src/content/ar/blog/post-1.md @@ -0,0 +1,23 @@ +--- +title: "كيفية بناء تطبيق بالتكنولوجيا الحديثة" +meta_title: "" +description: "this is meta description" +date: 2022-04-04T05:00:00Z +image: "/images/image-placeholder.png" +categories: ["Application", "Data", "Arabic"] +author: "John Doe" +tags: ["nextjs", "tailwind"] +draft: false +--- + +لا داعي للقلق بشأن إنشاء rutrum على سبيل المثال، venenatis sollicitudin urna. Aliquam عصر فولوتبات. عدد صحيح الاتحاد الأوروبي ipsum sem. Ut bibendum lacus الدهليزي مكسيموس سوسكيبيت. السيرة الذاتية الرائعة nibh iaculis neque blandit euismod. + +Lorem ipsum dolor sit amet consectetur adipisicing elit. لا حاجة إلى إنشاء aperiam. Itaque eligendi natus aperiam؟ استثناءات طاردة للسلبية خيار التعجيل السريع هو أديبيسسي دولوريم أوت إيوس! + +## التصميم الإبداعي + +Nam ut rutrum ex, venenatis sollicitudin urna. Aliquam عصر فولوتبات. عدد صحيح الاتحاد الأوروبي ipsum sem. Ut bibendum lacus الدهليزي مكسيموس suscipit. السيرة الذاتية الرائعة nibh iaculis neque blandit euismod. + +> لوريم إيبسوم دولور الجلوس أميت كونسيكتور أديبيسينج إيليت. لا حاجة إلى إنشاء aperiam. Itaque eligendi natus aperiam؟ استثناءات طاردة للسلبية خيار التعجيل السريع هو أديبيسسي دولوريم أوت إيوس! + +Lorem ipsum dolor sit amet consectetur adipisicing elit. لا حاجة إلى إنشاء aperiam. Itaque eligendi natus aperiam؟ استثناءات طاردة للسلبية خيار التعجيل السريع هو أديبيسسي دولوريم أوت إيوس! diff --git a/src/content/blog/post-2.md b/src/content/ar/blog/post-2.md similarity index 100% rename from src/content/blog/post-2.md rename to src/content/ar/blog/post-2.md diff --git a/src/content/blog/post-3.md b/src/content/ar/blog/post-3.md similarity index 100% rename from src/content/blog/post-3.md rename to src/content/ar/blog/post-3.md diff --git a/src/content/blog/post-4.md b/src/content/ar/blog/post-4.md similarity index 100% rename from src/content/blog/post-4.md rename to src/content/ar/blog/post-4.md diff --git a/src/content/contact/-index.md b/src/content/ar/contact/-index.md similarity index 100% rename from src/content/contact/-index.md rename to src/content/ar/contact/-index.md diff --git a/src/content/ar/homepage/-index.md b/src/content/ar/homepage/-index.md new file mode 100755 index 0000000..e7c56e4 --- /dev/null +++ b/src/content/ar/homepage/-index.md @@ -0,0 +1,53 @@ +--- +# Banner +banner: + title: "القالب المبدئي المثالي الذي تحتاجه لبدء مشروعك الفلكي" + content: "Astroplate هو قالب بداية مجاني مصمم باستخدام Astro وTailwindCSS، وهو يوفر كل ما تحتاجه لبدء مشروع Astro الخاص بك وتوفير الوقت الثمين." + image: "/images/banner.png" + button: + enable: true + label: "Get Started For Free" + link: "https://github.com/zeon-studio/astroplate" + +# Features +features: + - title: "What's Included in Astroplate" + image: "/images/service-1.png" + content: "Astroplate is a comprehensive starter template that includes everything you need to get started with your Astro project. What's Included in Astroplate" + bulletpoints: + - "10+ Pre-build pages" + - "95+ Google Pagespeed Score" + - "Build with Astro and TailwindCSS for easy and customizable styling" + - "Fully responsive on all devices" + - "SEO-optimized for better search engine rankings" + - "**Open-source and free** for personal and commercial use" + button: + enable: false + label: "Get Started Now" + link: "#" + + - title: "Discover the Key Features Of Astro" + image: "/images/service-2.png" + content: "Astro is an all-in-one web framework for building fast, content-focused websites. It offers a range of exciting features for developers and website creators. Some of the key features are:" + bulletpoints: + - "Zero JS, by default: No JavaScript runtime overhead to slow you down." + - "Customizable: Tailwind, MDX, and 100+ other integrations to choose from." + - "UI-agnostic: Supports React, Preact, Svelte, Vue, Solid, Lit and more." + button: + enable: true + label: "Get Started Now" + link: "https://github.com/zeon-studio/astroplate" + + - title: "The Top Reasons to Choose Astro for Your Next Project" + image: "/images/service-3.png" + content: "With Astro, you can build modern and content-focused websites without sacrificing performance or ease of use." + bulletpoints: + - "Instantly load static sites for better user experience and SEO." + - "Intuitive syntax and support for popular frameworks make learning and using Astro a breeze." + - "Use any front-end library or framework, or build custom components, for any project size." + - "Built on cutting-edge technology to keep your projects up-to-date with the latest web standards." + button: + enable: false + label: "" + link: "" +--- diff --git a/src/content/ar/pages/elements.mdx b/src/content/ar/pages/elements.mdx new file mode 100755 index 0000000..0ff30a4 --- /dev/null +++ b/src/content/ar/pages/elements.mdx @@ -0,0 +1,255 @@ +--- +title: "عناصر" +meta_title: "" +description: "this is meta description" +draft: false +--- + +# عنوان 1 + +## العنوان 2 + +### العنوان 3 + +#### العنوان 4 + +##### العنوان 5 + +###### العنوان 6 + +--- + +### فقرة + +هل أتيت إلى هنا من أجل شيء محدد أم مجرد تقريع للرايكر بشكل عام؟ وبالانطلاق إلى أقصى سرعة ممكنة، ظهرت للحظة وكأنك في مكانين في الوقت نفسه. لدينا مخرب على متن الطائرة. نحن نعلم أنك تتعامل بالخام المسروق. لكني أريد أن أتحدث عن محاولة اغتيال الملازم وورف. هل يمكن لأي شخص البقاء على قيد الحياة داخل منطقة النقل العازلة لمدة 75 عامًا؟ قدر. إنه يحمي الحمقى والأطفال الصغار والسفن. + +هل أتيت إلى هنا من أجل شيء محدد أم مجرد تقريع عام للرايكر؟ وبالانطلاق إلى أقصى سرعة ممكنة، ظهرت للحظة وكأنك في مكانين في الوقت نفسه. لدينا مخرب على متن الطائرة. نحن نعلم أنك تتعامل بالخام المسروق. لكني أريد أن أتحدث عن محاولة اغتيال الملازم وورف. هل يمكن لأي شخص البقاء على قيد الحياة داخل منطقة النقل العازلة لمدة 75 عامًا؟ قدر. إنه يحمي الحمقى والأطفال الصغار والسفن. + +--- + +### توكيد + +1. هل أتيت إلى هنا من أجل شيء **خاص** أم مجرد عام + +2. هل أتيت إلى هنا من أجل شيء ما على وجه الخصوص + +3. _هل أتيت إلى هنا_ + +4. هل أتيت إلى هنا من أجل ** شيء ما ** على وجه الخصوص + +5. هل أتيت إلى هنا من أجل شيء محدد؟ + +6. هل أتيت إلى هنا من أجل شيء محدد؟ + +7. سيتم تحويل عناوين URL وعناوين URL الموجودة بين قوسين إلى روابط تلقائيًا. [http://www.example.com](http://www.example.com) أو + +8. [http://www.example.com](http://www.example.com) وأحيانًا example.com (ولكن ليس على Github، على سبيل المثال). + +--- + +### وصلة + +[أنا رابط ذو نمط مضمّن](https://www.google.com) + +[أنا رابط على شكل سطري يحمل عنوانًا](https://www.google.com "صفحة Google الرئيسية") + +[أنا رابط ذو نمط مرجعي] [نص مرجعي عشوائي غير حساس لحالة الأحرف] + +[أنا مرجع نسبي لملف مستودع](../blob/master/LICENSE) + +[يمكنك استخدام الأرقام لتعريفات الارتباط ذات النمط المرجعي] [1] + +أو اتركه فارغًا واستخدم [رابط النص نفسه]. + +example.com (ولكن ليس على Github، على سبيل المثال). + +بعض النص لإظهار أن الروابط المرجعية يمكن أن تتبع لاحقًا. + +[نص مرجعي عشوائي غير حساس لحالة الأحرف]: https://www.themefisher.com +[1]: https://gethugothemes.com +[رابط النص نفسه]: https://www.getjekyllthemes.com + +--- + +### Ordered List + +1. List item +2. List item +3. List item +4. List item +5. List item + +--- + +### Unordered List + +- List item +- List item +- List item +- List item +- List item + +--- + +### Code and Syntax Highlighting + +#### HTML + +```html +

+``` + +--- + +#### CSS + +```css +img { + vertical-align: middle; + border: 0; + max-width: 100%; + height: auto; +} +``` + +--- + +#### JavaScript + +```javascript +window.addEventListener("load", (e) => { + document.querySelector(".preloader").style.display = "none"; +}); +``` + +--- + +### Button + + + diff --git a/src/pages/index.astro b/src/pages/[...lang]/index.astro similarity index 71% rename from src/pages/index.astro rename to src/pages/[...lang]/index.astro index 19d3f99..07b1ab8 100755 --- a/src/pages/index.astro +++ b/src/pages/[...lang]/index.astro @@ -1,12 +1,16 @@ --- import ImageMod from "@/components/ImageMod.astro"; +import config from "@/config/config.json"; import Base from "@/layouts/Base.astro"; +import { getListPage } from "@/lib/contentParser.astro"; import { markdownify } from "@/lib/utils/textConverter"; import CallToAction from "@/partials/CallToAction.astro"; import Testimonial from "@/partials/Testimonial.astro"; import type { Button, Feature } from "@/types"; -import { getEntry } from "astro:content"; +import type { ContentEntryMap } from "astro:content"; +import { getCollection } from "astro:content"; import { FaCheck } from "react-icons/fa"; +const { defaultLang } = config.language; interface Homepage { banner: { @@ -18,10 +22,35 @@ interface Homepage { features: Feature[]; } -const homepage = await getEntry("homepage", "-index"); -const testimonial = await getEntry("sections", "testimonial"); -const call_to_action = await getEntry("sections", "call-to-action"); -const { banner, features }: Homepage = homepage.data; +export function getStaticPaths() { + const { supported } = config.language; + const paths = supported.map((lang) => ({ + params: { lang: lang || undefined }, + })); + return paths; +} + +const { lang } = Astro.params; +const homepage = await getListPage("homepage", lang as keyof ContentEntryMap); + +// const testimonial = await getEntry("sections", "testimonial"); +// const call_to_action = await getEntry("sections", "call-to-action"); +const { banner, features }: Homepage = homepage[0].data; + +const testimonial = await getCollection( + (lang as keyof ContentEntryMap) || defaultLang, + ({ id }) => { + return id.startsWith("sections/testimonial") && !id.endsWith("-index.md"); + } +); +const call_to_action = await getCollection( + (lang as keyof ContentEntryMap) || defaultLang, + ({ id }) => { + return ( + id.startsWith("sections/call-to-action") && !id.endsWith("-index.md") + ); + } +); --- @@ -109,6 +138,6 @@ const { banner, features }: Homepage = homepage.data; } - - + + diff --git a/src/pages/authors/index.astro b/src/pages/authors/index.astro deleted file mode 100755 index 8df557f..0000000 --- a/src/pages/authors/index.astro +++ /dev/null @@ -1,29 +0,0 @@ ---- -import AuthorCard from "@/components/AuthorCard.astro"; -import Base from "@/layouts/Base.astro"; -import { getSinglePage } from "@/lib/contentParser.astro"; -import PageHeader from "@/partials/PageHeader.astro"; -import { getEntry } from "astro:content"; - -const COLLECTION_FOLDER = "authors"; - -const authorIndex = await getEntry(COLLECTION_FOLDER, "-index"); -const authors = await getSinglePage(COLLECTION_FOLDER); ---- - - - -
-
-
- { - authors.map((author) => ( -
- -
- )) - } -
-
-
- diff --git a/src/pages/blog/[single].astro b/src/pages/blog/[single].astro deleted file mode 100755 index 984477b..0000000 --- a/src/pages/blog/[single].astro +++ /dev/null @@ -1,30 +0,0 @@ ---- -import Base from "@/layouts/Base.astro"; -import PostSingle from "@/layouts/PostSingle.astro"; -import { getSinglePage } from "@/lib/contentParser.astro"; - -export async function getStaticPaths() { - const BLOG_FOLDER = "blog"; - const posts = await getSinglePage(BLOG_FOLDER); - - const paths = posts.map((post) => ({ - params: { - single: post.slug, - }, - props: { post }, - })); - return paths; -} - -const { post } = Astro.props; -const { title, meta_title, description, image } = post.data; ---- - - - - diff --git a/src/pages/tags/[tag].astro b/src/pages/tags/[tag].astro deleted file mode 100755 index cd81405..0000000 --- a/src/pages/tags/[tag].astro +++ /dev/null @@ -1,45 +0,0 @@ ---- -import BlogCard from "@/components/BlogCard.astro"; -import Base from "@/layouts/Base.astro"; -import { getSinglePage } from "@/lib/contentParser.astro"; -import { getTaxonomy } from "@/lib/taxonomyParser.astro"; -import { sortByDate } from "@/lib/utils/sortFunctions"; -import taxonomyFilter from "@/lib/utils/taxonomyFilter"; -import PageHeader from "@/partials/PageHeader.astro"; - -export async function getStaticPaths() { - const BLOG_FOLDER = "blog"; - const tags = await getTaxonomy(BLOG_FOLDER, "tags"); - - return tags.map((tag) => { - return { - params: { tag }, - }; - }); -} - -const { tag } = Astro.params; - -// get posts by tag -const BLOG_FOLDER = "blog"; -const posts = await getSinglePage(BLOG_FOLDER); -const filterByTags = taxonomyFilter(posts, "tags", tag!); -const sortedPosts = sortByDate(filterByTags); ---- - - - -
-
-
- { - sortedPosts.map((post) => ( -
- -
- )) - } -
-
-
- diff --git a/src/pages/tags/index.astro b/src/pages/tags/index.astro deleted file mode 100755 index 0989c16..0000000 --- a/src/pages/tags/index.astro +++ /dev/null @@ -1,39 +0,0 @@ ---- -import Base from "@/layouts/Base.astro"; -import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro"; -import { humanize } from "@/lib/utils/textConverter"; -import PageHeader from "@/partials/PageHeader.astro"; - -const BLOG_FOLDER = "blog"; - -const tags = await getTaxonomy(BLOG_FOLDER, "tags"); -const allTags = await getAllTaxonomy(BLOG_FOLDER, "tags"); ---- - - - -
- -
- diff --git a/src/styles/base.scss b/src/styles/base.scss index 2fac7c2..b568330 100755 --- a/src/styles/base.scss +++ b/src/styles/base.scss @@ -3,7 +3,7 @@ html { } body { - @apply bg-body text-base dark:bg-darkmode-body font-primary font-normal leading-relaxed text-text dark:text-darkmode-text; + @apply bg-body dark:bg-darkmode-body font-primary font-normal leading-relaxed text-text dark:text-darkmode-text; } h1, From b92a4a4c6a86759b7854749925a753c24683189b Mon Sep 17 00:00:00 2001 From: Al Murad Uzzaman Date: Tue, 14 May 2024 16:23:32 +0600 Subject: [PATCH 02/23] breadcrumbs && jsonGenerator updated --- scripts/jsonGenerator.js | 77 ++++++++++++++---------- src/config/language.json | 20 ++++++ src/layouts/components/Breadcrumbs.astro | 18 ++++-- 3 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 src/config/language.json diff --git a/scripts/jsonGenerator.js b/scripts/jsonGenerator.js index 8aee1ac..f63091a 100644 --- a/scripts/jsonGenerator.js +++ b/scripts/jsonGenerator.js @@ -1,45 +1,56 @@ const fs = require("fs"); const path = require("path"); const matter = require("gray-matter"); +const languages = require("../src/config/language.json"); -const CONTENT_DEPTH = 2; const JSON_FOLDER = "./.json"; -const BLOG_FOLDER = "src/content/blog"; +const CONTENT_ROOT = "src/content"; +const CONTENT_DEPTH = 3; +const BLOG_FOLDER = "blog"; // get data from markdown const getData = (folder, groupDepth) => { - const getPath = fs.readdirSync(folder); - const removeIndex = getPath.filter((item) => !item.startsWith("-")); + // get paths + const getPaths = languages + .map((lang) => { + const dir = path.join(CONTENT_ROOT, lang.contentDir, folder); + return fs + .readdirSync(dir) + .filter( + (filename) => + !filename.startsWith("-") && + (filename.endsWith(".md") || filename.endsWith(".mdx")), + ) + .map((filename) => { + const filepath = path.join(dir, filename); + const stats = fs.statSync(filepath); + const isFolder = stats.isDirectory(); - const getPaths = removeIndex.flatMap((filename) => { - const filepath = path.join(folder, filename); - const stats = fs.statSync(filepath); - const isFolder = stats.isDirectory(); + if (isFolder) { + return getData(filepath, groupDepth); + } else { + const file = fs.readFileSync(filepath, "utf-8"); + const { data, content } = matter(file); + const pathParts = filepath.split(path.sep); + const slug = + data.slug || + pathParts + .slice(CONTENT_DEPTH) + .join("/") + .replace(/\.[^/.]+$/, ""); + const group = pathParts[groupDepth]; - if (isFolder) { - return getData(filepath, groupDepth); - } else if (filename.endsWith(".md") || filename.endsWith(".mdx")) { - const file = fs.readFileSync(filepath, "utf-8"); - const { data, content } = matter(file); - const pathParts = filepath.split(path.sep); - const slug = - data.slug || - pathParts - .slice(CONTENT_DEPTH) - .join("/") - .replace(/\.[^/.]+$/, ""); - const group = pathParts[groupDepth]; - - return { - group: group, - slug: slug, - frontmatter: data, - content: content, - }; - } else { - return []; - } - }); + return { + lang: lang.languageCode, + group: group, + slug: slug, + frontmatter: data, + content: content, + }; + } + }); + }) + .flat(); const publishedPages = getPaths.filter( (page) => !page.frontmatter?.draft && page, @@ -56,7 +67,7 @@ try { // create json files fs.writeFileSync( `${JSON_FOLDER}/posts.json`, - JSON.stringify(getData(BLOG_FOLDER, 2)), + JSON.stringify(getData(BLOG_FOLDER, 3)), ); // merger json files for search diff --git a/src/config/language.json b/src/config/language.json new file mode 100644 index 0000000..3ae09d3 --- /dev/null +++ b/src/config/language.json @@ -0,0 +1,20 @@ +[ + { + "languageName": "En", + "languageCode": "en", + "contentDir": "en", + "weight": 1 + }, + { + "languageName": "Fr", + "languageCode": "fr", + "contentDir": "fr", + "weight": 2 + }, + { + "languageName": "Ar", + "languageCode": "ar", + "contentDir": "ar", + "weight": 3 + } +] diff --git a/src/layouts/components/Breadcrumbs.astro b/src/layouts/components/Breadcrumbs.astro index ed67ed1..fb029b1 100644 --- a/src/layouts/components/Breadcrumbs.astro +++ b/src/layouts/components/Breadcrumbs.astro @@ -1,19 +1,28 @@ --- import { humanize } from "@/lib/utils/textConverter"; +import config from "@/config/config.json"; + +const { supported } = config.language; const { className }: { className?: string } = Astro.props; const paths = Astro.url.pathname.split("/").filter((x) => x); + +let lang = ""; +if (supported.includes(paths[0])) { + lang = paths.shift()!; +} + let parts = [ { label: "Home", - href: "/", - "aria-label": Astro.url.pathname === "/" ? "page" : undefined, + href: `/${lang}`, + "aria-label": Astro.url.pathname === `/${lang}` || Astro.url.pathname === `/${lang}/` ? "page" : undefined, }, ]; paths.forEach((label: string, i: number) => { - const href = `/${paths.slice(0, i + 1).join("/")}`; + const href = `/${lang}/${paths.slice(0, i + 1).join("/")}`; label !== "page" && parts.push({ label: humanize(label.replace(".html", "").replace(/[-_]/g, " ")) || "", @@ -21,6 +30,7 @@ paths.forEach((label: string, i: number) => { "aria-label": Astro.url.pathname === href ? "page" : undefined, }); }); + --- - +; diff --git a/src/lib/utils/i18nUtils.ts b/src/lib/utils/i18nUtils.ts index 2d30063..92ed301 100644 --- a/src/lib/utils/i18nUtils.ts +++ b/src/lib/utils/i18nUtils.ts @@ -1,8 +1,6 @@ import config from "@/config/config.json"; import languagesJSON from "@/config/language.json"; import { getRelativeLocaleUrl } from "astro:i18n"; -import fs from "fs"; -import path from "path"; const { default_language } = config.settings; const locales: { [key: string]: any } = {}; @@ -31,20 +29,57 @@ export function getLangFromUrl(url: URL): string { return default_language; } +// export const getTranslations = async (lang: string) => { +// const menu = await import( +// `../../config/menu.${lang || default_language}.json` +// ); +// const dictionary = await import( +// `../../i18n/${lang || default_language}.json` +// ); +// return { ...menu, ...dictionary }; +// }; + +// export const supportedLang = [""].concat( +// languagesJSON.map((lang) => lang.languageCode), +// ); +// Function to construct the URL based on trailing_slash value + export const getTranslations = async (lang: string) => { - const menu = await import( - `../../config/menu.${lang || default_language}.json` - ); - const dictionary = await import( - `../../i18n/${lang || default_language}.json` - ); - return { ...menu, ...dictionary }; + const { + default_language, + disable_languages, + }: { default_language: string; disable_languages: string[] } = + config.settings; + + if (disable_languages.includes(lang)) { + lang = default_language; + } + + let language = languagesJSON.find((l) => l.languageCode === lang); + + if (!language) { + lang = default_language; + language = languagesJSON.find((l) => l.languageCode === default_language); + } + + if (!language) { + throw new Error("Default language not found"); + } + + const contentDir = language.contentDir; + + let menu, dictionary; + try { + menu = await import(`../../config/menu.${lang}.json`); + dictionary = await import(`../../i18n/${lang}.json`); + } catch (error) { + menu = await import(`../../config/menu.${default_language}.json`); + dictionary = await import(`../../i18n/${default_language}.json`); + } + + return { ...menu.default, ...dictionary.default, contentDir }; }; -export const supportedLang = [""].concat( - languagesJSON.map((lang) => lang.languageCode), -); -// Function to construct the URL based on trailing_slash value export const constructUrl = ( url: string, lang: string, @@ -76,3 +111,13 @@ export const constructUrl = ( return constructedUrl; }; + +const supportedLang = ["", ...languagesJSON.map((lang) => lang.languageCode)]; +const disabledLanguages = config.settings.disable_languages as string[]; + +// Filter out disabled languages from supportedLang +const filteredSupportedLang = supportedLang.filter( + (lang) => !disabledLanguages.includes(lang), +); + +export { filteredSupportedLang as supportedLang }; diff --git a/src/lib/utils/loadMenu.ts b/src/lib/utils/loadMenu.ts deleted file mode 100644 index 6ed450a..0000000 --- a/src/lib/utils/loadMenu.ts +++ /dev/null @@ -1,41 +0,0 @@ -import fs from "fs"; -import path from "path"; -import languages from "@/config/language.json"; - -export interface ChildNavigationLink { - name: string; - url: string; -} - -export interface NavigationLink { - name: string; - url: string; - hasChildren?: boolean; - children?: ChildNavigationLink[]; -} - -interface Menu { - main: NavigationLink[]; - footer: NavigationLink[]; -} - -export function loadMenu(lang: string): Menu { - // Find the language object based on the language code - const language = languages.find((l) => l.languageCode === lang); - - if (!language) { - throw new Error( - `Language '${lang}' not found in the list of supported languages.`, - ); - } - - // Load menu data based on the language code - const menuPath: string = path.join( - process.cwd(), - "src", - "config", - `menu.${language.languageCode}.json`, - ); - const menuData: string = fs.readFileSync(menuPath, "utf-8"); - return JSON.parse(menuData) as Menu; -} diff --git a/src/pages/404.astro b/src/pages/404.astro index 80fd066..6756ec0 100755 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -2,11 +2,13 @@ import config from "@/config/config.json"; import Base from "@/layouts/Base.astro"; import { + constructUrl, getLangFromUrl, getTranslations, supportedLang, } from "@/lib/utils/i18nUtils"; import type { ContentEntryMap } from "astro:content"; +const { trailing_slash } = config.site; export function getStaticPaths() { const paths = supportedLang.map((lang) => ({ @@ -15,11 +17,23 @@ export function getStaticPaths() { return paths; } -const lang = getLangFromUrl(Astro.url); +let lang = getLangFromUrl(Astro.url); + +// Check if the current language is disabled +const disabledLanguages = config.settings.disable_languages as string[]; +if (disabledLanguages.includes(lang)) { + // Redirect to the default language or handle as per your application logic + lang = config.settings.default_language; +} + const { page_not_found_content, page_not_found, back_to_home } = await getTranslations(lang as keyof ContentEntryMap); -const { default_language } = config.settings; -const href = lang && lang !== default_language ? `/${lang}/` : "/"; +const href = constructUrl( + "/", + lang, + config.settings.default_language, + trailing_slash +); --- diff --git a/src/pages/[...lang]/contact.astro b/src/pages/[...lang]/contact.astro index 824c4c4..1a30b39 100644 --- a/src/pages/[...lang]/contact.astro +++ b/src/pages/[...lang]/contact.astro @@ -4,6 +4,7 @@ import Base from "@/layouts/Base.astro"; import { getListPage } from "@/lib/contentParser.astro"; import { getTranslations, supportedLang } from "@/lib/utils/i18nUtils"; import PageHeader from "@/partials/PageHeader.astro"; +import type { CollectionKey } from "astro:content"; import { type ContentEntryMap } from "astro:content"; export function getStaticPaths() { @@ -14,7 +15,10 @@ export function getStaticPaths() { } const { lang } = Astro.params; -const contact = await getListPage("contact", lang as keyof ContentEntryMap); +const contact: any = await getListPage( + "contact" as CollectionKey, + lang as keyof ContentEntryMap +); const { contact_form_action }: { contact_form_action: string } = config.params; const { title, description, meta_title, image } = contact[0].data; diff --git a/src/pages/[...lang]/index.astro b/src/pages/[...lang]/index.astro index 93c201a..6265732 100755 --- a/src/pages/[...lang]/index.astro +++ b/src/pages/[...lang]/index.astro @@ -1,6 +1,5 @@ --- import ImageMod from "@/components/ImageMod.astro"; -import config from "@/config/config.json"; import Base from "@/layouts/Base.astro"; import { getListPage, getSinglePage } from "@/lib/contentParser.astro"; import { supportedLang } from "@/lib/utils/i18nUtils"; @@ -10,8 +9,6 @@ import Testimonial from "@/partials/Testimonial.astro"; import type { Button, Feature } from "@/types"; import type { ContentCollectionKey, ContentEntryMap } from "astro:content"; import { FaCheck } from "react-icons/fa"; -const { default_language } = config.settings; - interface Homepage { banner: { title: string; @@ -32,18 +29,18 @@ export function getStaticPaths() { const { lang } = Astro.params; const homepage: any = await getListPage( "homepage" as ContentCollectionKey, - lang as keyof ContentEntryMap, + lang as keyof ContentEntryMap ); -const { banner, features } = homepage[0].data; +const { banner, features }: Homepage = homepage[0].data; const testimonial = await getSinglePage( "sections/testimonial" as ContentCollectionKey, - lang as keyof ContentEntryMap, + lang as keyof ContentEntryMap ); const call_to_action = await getSinglePage( "sections/call-to-action" as ContentCollectionKey, - lang as keyof ContentEntryMap, + lang as keyof ContentEntryMap ); --- From 340500efcc716d599c08c3c93f2b79a56b5edf00 Mon Sep 17 00:00:00 2001 From: Al Murad Uzzaman Date: Sun, 19 May 2024 17:40:46 +0600 Subject: [PATCH 13/23] worked with lang subdir --- astro.config.mjs | 17 +++++--- src/config/config.json | 3 +- src/layouts/PostSingle.astro | 34 ++++++++++++---- src/layouts/components/BlogCard.astro | 35 +++++++++++----- src/layouts/components/Logo.astro | 17 ++++++-- src/layouts/partials/Footer.astro | 24 ++++++++++- src/layouts/partials/Header.astro | 53 ++++++++++--------------- src/layouts/partials/PostSidebar.astro | 24 ++++++++--- src/lib/utils/i18nUtils.ts | 19 +-------- src/pages/[...lang]/blog/[single].astro | 4 +- 10 files changed, 145 insertions(+), 85 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 68d434a..8f2beda 100755 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -7,6 +7,16 @@ import { defineConfig, squooshImageService } from "astro/config"; import remarkCollapse from "remark-collapse"; import remarkToc from "remark-toc"; import config from "./src/config/config.json"; +import languagesJSON from "./src/config/language.json"; +const { default_language } = config.settings; + +const supportedLang = [...languagesJSON.map((lang) => lang.languageCode)]; +const disabledLanguages = config.settings.disable_languages; + +// Filter out disabled languages from supportedLang +const filteredSupportedLang = supportedLang.filter( + (lang) => !disabledLanguages.includes(lang), +); // https://astro.build/config export default defineConfig({ @@ -14,11 +24,8 @@ export default defineConfig({ base: config.site.base_path ? config.site.base_path : "/", trailingSlash: config.site.trailing_slash ? "always" : "never", i18n: { - locales: ["en", "fr", "ar"], - defaultLocale: "en", - routing: { - prefixDefaultLocale: false, - }, + locales: filteredSupportedLang, + defaultLocale: default_language, }, image: { service: squooshImageService(), diff --git a/src/config/config.json b/src/config/config.json index 382577f..83920f1 100755 --- a/src/config/config.json +++ b/src/config/config.json @@ -21,7 +21,8 @@ "summary_length": 200, "blog_folder": "blog", "default_language": "en", - "disable_languages": [] + "disable_languages": [], + "default_language_in_path": false }, "params": { diff --git a/src/layouts/PostSingle.astro b/src/layouts/PostSingle.astro index 3efce71..e9eeefc 100755 --- a/src/layouts/PostSingle.astro +++ b/src/layouts/PostSingle.astro @@ -5,12 +5,14 @@ import config from "@/config/config.json"; import Disqus from "@/helpers/Disqus"; import { getSinglePage } from "@/lib/contentParser.astro"; import dateFormat from "@/lib/utils/dateFormat"; +import { constructUrl } from "@/lib/utils/i18nUtils"; import similarItems from "@/lib/utils/similarItems"; import { humanize, markdownify, slugify } from "@/lib/utils/textConverter"; import type { ContentEntryMap } from "astro:content"; import { FaRegClock, FaRegFolder, FaRegUserCircle } from "react-icons/fa"; import ImageMod from "./components/ImageMod.astro"; -const { default_language } = config.settings; +const { default_language, default_language_in_path } = config.settings; +const { trailing_slash } = config.site; const COLLECTION_FOLDER = "blog"; const { post } = Astro.props; @@ -18,11 +20,29 @@ const { lang } = Astro.params; const posts = await getSinglePage( COLLECTION_FOLDER, - lang as keyof ContentEntryMap, + lang as keyof ContentEntryMap ); const similarPosts = similarItems(post, posts); const { Content } = await post.render(); const { title, description, author, categories, image, date, tags } = post.data; + +const constructLocalizedUrl = (url: string) => { + if (lang === default_language) { + return constructUrl( + default_language_in_path ? `/${lang}${url}` : url, + lang, + default_language, + trailing_slash + ); + } else { + return constructUrl( + url, + lang as keyof ContentEntryMap, + default_language, + trailing_slash + ); + } +}; ---
@@ -46,9 +66,7 @@ const { title, description, author, categories, image, date, tags } = post.data;

{plainify(data.body?.slice(0, 100))} diff --git a/src/layouts/components/Pagination.astro b/src/layouts/components/Pagination.astro index c5eb4a5..8b9722c 100644 --- a/src/layouts/components/Pagination.astro +++ b/src/layouts/components/Pagination.astro @@ -1,5 +1,9 @@ --- -import { getLangFromUrl } from "@/lib/utils/i18nUtils"; +import { constructUrl, getLangFromUrl } from "@/lib/utils/i18nUtils"; +import config from "@/config/config.json"; +import type { ContentEntryMap } from "astro:content"; +const { default_language, default_language_in_path } = config.settings; +const { trailing_slash } = config.site; const lang = getLangFromUrl(Astro.url); @@ -8,11 +12,7 @@ type Pagination = { currentPage?: number; totalPages?: number; }; -const { - section, - currentPage = 1, - totalPages = 1 -}: Pagination = Astro.props; +const { section, currentPage = 1, totalPages = 1 }: Pagination = Astro.props; const indexPageLink = currentPage === 2; const hasPrevPage = currentPage > 1; @@ -22,6 +22,24 @@ let pageList: number[] = []; for (let i = 1; i <= totalPages; i++) { pageList.push(i); } + +const constructLocalizedUrl = (url: string) => { + if (lang === default_language) { + return constructUrl( + default_language_in_path ? `/${lang}${url}` : url, + lang, + default_language, + trailing_slash, + ); + } else { + return constructUrl( + url, + lang as keyof ContentEntryMap, + default_language, + trailing_slash, + ); + } +}; --- { @@ -35,8 +53,10 @@ for (let i = 1; i <= totalPages; i++) { @@ -85,23 +105,25 @@ for (let i = 1; i <= totalPages; i++) { ) : ( {pagination} - ) + ), )} {/* next page */} {hasNextPage ? ( Next @@ -140,4 +162,3 @@ for (let i = 1; i <= totalPages; i++) { ) } - diff --git a/src/pages/[...lang]/[regular].astro b/src/pages/[...lang]/[regular].astro index 3d95f11..2f9da2c 100755 --- a/src/pages/[...lang]/[regular].astro +++ b/src/pages/[...lang]/[regular].astro @@ -10,7 +10,7 @@ export async function getStaticPaths() { supportedLang.map(async (lang) => { const pages = await getSinglePage("pages", lang as keyof ContentEntryMap); - return pages.map((page) => ({ + return pages.map((page: any) => ({ params: { lang: lang || undefined, regular: page.slug.split("/").pop(), @@ -19,7 +19,7 @@ export async function getStaticPaths() { page, }, })); - }) + }), ); return paths.flat(); } diff --git a/src/pages/[...lang]/authors/index.astro b/src/pages/[...lang]/authors/index.astro index c144956..c95249e 100755 --- a/src/pages/[...lang]/authors/index.astro +++ b/src/pages/[...lang]/authors/index.astro @@ -16,13 +16,13 @@ export function getStaticPaths() { } const { lang } = Astro.params; -const authorIndex = await getListPage( +const authorIndex: any = await getListPage( COLLECTION_FOLDER, - lang as keyof ContentEntryMap + lang as keyof ContentEntryMap, ); const authors = await getSinglePage( COLLECTION_FOLDER, - lang as keyof ContentEntryMap + lang as keyof ContentEntryMap, ); --- diff --git a/src/pages/[...lang]/blog/page/[slug].astro b/src/pages/[...lang]/blog/page/[slug].astro index 8a3c25d..945d6c0 100755 --- a/src/pages/[...lang]/blog/page/[slug].astro +++ b/src/pages/[...lang]/blog/page/[slug].astro @@ -10,10 +10,14 @@ import { sortByDate } from "@/lib/utils/sortFunctions"; import PageHeader from "@/partials/PageHeader.astro"; import PostSidebar from "@/partials/PostSidebar.astro"; import type { ContentEntryMap } from "astro:content"; -import { getCollection } from "astro:content"; const BLOG_FOLDER = "blog"; +const { default_language } = config.settings; -const { slug, lang } = Astro.params; +let { slug, lang } = Astro.params; + +if (!lang) { + lang = default_language; +} const postIndex: any = await getListPage( BLOG_FOLDER, @@ -41,13 +45,10 @@ export async function getStaticPaths() { const paths = await Promise.all( supportedLang.map(async (lang) => { - const posts = await getCollection( + const posts = await getSinglePage( + BLOG_FOLDER, lang as keyof ContentEntryMap, - ({ id }: any) => { - return id.startsWith(BLOG_FOLDER) && !id.endsWith("-index.md"); - }, ); - const totalPages = Math.ceil(posts.length / config.settings.pagination); const langString = lang.toString(); const langPaths = []; @@ -55,7 +56,7 @@ export async function getStaticPaths() { for (let i = 1; i < totalPages; i++) { langPaths.push({ params: { - lang: langString, + lang: langString || undefined, slug: (i + 1).toString(), }, }); diff --git a/src/pages/[...lang]/categories/index.astro b/src/pages/[...lang]/categories/index.astro index 49e8c69..c8af314 100755 --- a/src/pages/[...lang]/categories/index.astro +++ b/src/pages/[...lang]/categories/index.astro @@ -1,10 +1,13 @@ --- +import config from "@/config/config.json"; import Base from "@/layouts/Base.astro"; import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro"; -import { supportedLang } from "@/lib/utils/i18nUtils"; +import { constructUrl, supportedLang } from "@/lib/utils/i18nUtils"; import { humanize } from "@/lib/utils/textConverter"; import PageHeader from "@/partials/PageHeader.astro"; import type { ContentEntryMap } from "astro:content"; +const { default_language, default_language_in_path } = config.settings; +const { trailing_slash } = config.site; export function getStaticPaths() { const paths = supportedLang.map((lang) => ({ @@ -13,10 +16,32 @@ export function getStaticPaths() { return paths; } -const { lang } = Astro.params; +let { lang } = Astro.params; +if (!lang) { + lang = default_language; +} + const langCollection: keyof ContentEntryMap = lang as keyof ContentEntryMap; const categories = await getTaxonomy(langCollection, "categories"); const allCategories = await getAllTaxonomy(langCollection, "categories"); + +const constructLocalizedUrl = (url: string) => { + if (lang === default_language) { + return constructUrl( + default_language_in_path ? `/${lang}${url}` : url, + lang, + default_language, + trailing_slash, + ); + } else { + return constructUrl( + url, + lang as keyof ContentEntryMap, + default_language, + trailing_slash, + ); + } +}; --- @@ -30,7 +55,7 @@ const allCategories = await getAllTaxonomy(langCollection, "categories"); return (

  • {humanize(category)}{" "} diff --git a/src/pages/[...lang]/tags/index.astro b/src/pages/[...lang]/tags/index.astro index cf25d0b..380957c 100644 --- a/src/pages/[...lang]/tags/index.astro +++ b/src/pages/[...lang]/tags/index.astro @@ -1,10 +1,13 @@ --- +import config from "@/config/config.json"; import Base from "@/layouts/Base.astro"; import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro"; -import { supportedLang } from "@/lib/utils/i18nUtils"; +import { constructUrl, supportedLang } from "@/lib/utils/i18nUtils"; import { humanize } from "@/lib/utils/textConverter"; import PageHeader from "@/partials/PageHeader.astro"; import type { ContentEntryMap } from "astro:content"; +const { default_language, default_language_in_path } = config.settings; +const { trailing_slash } = config.site; export function getStaticPaths() { const paths = supportedLang.map((lang) => ({ @@ -13,10 +16,32 @@ export function getStaticPaths() { return paths; } -const { lang } = Astro.params; +let { lang } = Astro.params; + +if (!lang) { + lang = default_language; +} const langCollection: keyof ContentEntryMap = lang as keyof ContentEntryMap; const tags = await getTaxonomy(langCollection, "tags"); const allTags = await getAllTaxonomy(langCollection, "tags"); + +const constructLocalizedUrl = (url: string) => { + if (lang === default_language) { + return constructUrl( + default_language_in_path ? `/${lang}${url}` : url, + lang, + default_language, + trailing_slash, + ); + } else { + return constructUrl( + url, + lang as keyof ContentEntryMap, + default_language, + trailing_slash, + ); + } +}; --- @@ -30,7 +55,7 @@ const allTags = await getAllTaxonomy(langCollection, "tags"); return (
  • {humanize(tag)}{" "} From ae35d98eee88b77437dabea3fd7f812cdbdce733 Mon Sep 17 00:00:00 2001 From: Al Murad Uzzaman Date: Mon, 20 May 2024 09:35:09 +0600 Subject: [PATCH 15/23] ; removed from header --- package.json | 2 +- src/i18n/en.json | 1 - src/i18n/fr.json | 1 - src/layouts/partials/Header.astro | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e166388..7ad0270 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "astroplate", - "version": "3.4.3", + "version": "4.0.0", "description": "Astro and Tailwindcss boilerplate", "author": "zeon.studio", "license": "MIT", diff --git a/src/i18n/en.json b/src/i18n/en.json index cad49ee..64f04bf 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -1,7 +1,6 @@ { "full_name": "Full Name", "full_name_placeholder": "Enter your full name", - "mail": "Work Email", "mail_placeholder": "john.doe@email.com", "message": "Anything else?", "message_placeholder": "Your message here...", diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 91948b0..62f4e06 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -1,7 +1,6 @@ { "full_name": "Nom complet", "full_name_placeholder": "Entrez votre nom complet", - "mail": "E-mail de travail", "mail_placeholder": "john.doe@email.com", "message": "Autre chose?", "message_placeholder": "Votre message ici...", diff --git a/src/layouts/partials/Header.astro b/src/layouts/partials/Header.astro index b673055..94eefe7 100755 --- a/src/layouts/partials/Header.astro +++ b/src/layouts/partials/Header.astro @@ -173,4 +173,4 @@ const constructLocalizedUrl = (url: string) => { } -; + From e7da8ab6df3268ad838249151cf3e25479dd73c3 Mon Sep 17 00:00:00 2001 From: Al Murad Uzzaman Date: Mon, 20 May 2024 12:15:34 +0600 Subject: [PATCH 16/23] slugSelector fn added --- src/layouts/PostSingle.astro | 33 ++---- src/layouts/components/AuthorCard.astro | 21 +--- src/layouts/components/BlogCard.astro | 30 ++---- src/layouts/components/Logo.astro | 23 +--- src/layouts/components/Pagination.astro | 38 ++----- src/layouts/partials/Footer.astro | 26 +---- src/layouts/partials/Header.astro | 38 ++----- src/layouts/partials/PostSidebar.astro | 23 +--- src/lib/contentParser.astro | 16 ++- src/lib/languageParser.astro | 118 +++++++++++++++++++++ src/pages/404.astro | 15 +-- src/pages/[...lang]/categories/index.astro | 26 +---- src/pages/[...lang]/tags/index.astro | 26 +---- 13 files changed, 181 insertions(+), 252 deletions(-) create mode 100644 src/lib/languageParser.astro diff --git a/src/layouts/PostSingle.astro b/src/layouts/PostSingle.astro index f4a95f1..9042b08 100755 --- a/src/layouts/PostSingle.astro +++ b/src/layouts/PostSingle.astro @@ -4,15 +4,14 @@ import Share from "@/components/Share.astro"; import config from "@/config/config.json"; import Disqus from "@/helpers/Disqus"; import { getSinglePage } from "@/lib/contentParser.astro"; +import { slugSelector } from "@/lib/languageParser.astro"; import dateFormat from "@/lib/utils/dateFormat"; -import { constructUrl } from "@/lib/utils/i18nUtils"; import similarItems from "@/lib/utils/similarItems"; import { humanize, markdownify, slugify } from "@/lib/utils/textConverter"; import type { ContentEntryMap } from "astro:content"; import { FaRegClock, FaRegFolder, FaRegUserCircle } from "react-icons/fa"; import ImageMod from "./components/ImageMod.astro"; -const { default_language, default_language_in_path } = config.settings; -const { trailing_slash } = config.site; +const { default_language } = config.settings; const COLLECTION_FOLDER = "blog"; const { post } = Astro.props; @@ -24,29 +23,11 @@ if (!lang) { const posts = await getSinglePage( COLLECTION_FOLDER, - lang as keyof ContentEntryMap, + lang as keyof ContentEntryMap ); const similarPosts = similarItems(post, posts); const { Content } = await post.render(); const { title, description, author, categories, image, date, tags } = post.data; - -const constructLocalizedUrl = (url: string) => { - if (lang === default_language) { - return constructUrl( - default_language_in_path ? `/${lang}${url}` : url, - lang, - default_language, - trailing_slash, - ); - } else { - return constructUrl( - url, - lang as keyof ContentEntryMap, - default_language, - trailing_slash, - ); - } -}; ---
    @@ -70,7 +51,7 @@ const constructLocalizedUrl = (url: string) => {