diff --git a/.astro-i18n/generated.d.ts b/.astro-i18n/generated.d.ts deleted file mode 100755 index 1750f79..0000000 --- a/.astro-i18n/generated.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -type DefaultLangCode = "fr" -type SupportedLangCode = "en" -type LangCode = DefaultLangCode | SupportedLangCode -type RouteUri = | "/articles/[slug]" | "/articles" | "/agments/[slug]" | "/agments" | "/references" | "/veille" | "/" | "/plan-du-site" -type RouteParams = {"/articles/[slug]": { "slug": string; }; "/articles": undefined; "/agments/[slug]": { "slug": string; }; "/agments": undefined; "/references": undefined; "/veille": undefined; "/": undefined; "/plan-du-site": undefined; } -type TranslationPath = "accueil" | "tagline" | "copyright" | "contact.title" | "contact.email" | "contact.tel" | "contenuVide" | "header.skipLink" | "header.mainNav" | "header.homeLink" | "sitemap" | "prevNext.contenus" | "prevNext.precedent" | "prevNext.suivant" | "article.titre" | "article.tagline" | "article.published" | "meta.publication" | "meta.modification" | "meta.credit" | "fragments.titre" | "fragments.tagline" | "references.titre" | "references.slug" | "references.cta" | "references.tagline" | "veille.titre" | "veille.tagline" | "erreur.introuvable" | "erreur.autre" | "erreur.lienRetour" | "seo.meta.description" | "seo.article.title" | "seo.article.description" | "seo.code.title" | "seo.code.description" | "seo.references.title" | "seo.references.description" | "index.articles.pageName" | "index.articles.subtitle" | "index.fragments.pageName" | "index.fragments.subtitle" | "index.references.pageName" | "index.references.subtitle" | "index.veille.pageName" | "index.veille.subtitle" | "index.title" | "index.subtitle" | "index.quoi" | "index.comment" | "index.opensource" | "index.writing" | "index.latestProjects" | "index.latestArticles" | "index.allProjects" | "index.allArticles" | "index.latestSnippets" | "index.allSnippets" | "index.toc" | "contact.contenuVide" -type TranslationOptions = { "accueil": {} | undefined; "tagline": {} | undefined; "copyright": {} | undefined; "contact.title": {} | undefined; "contact.email": {} | undefined; "contact.tel": {} | undefined; "contenuVide": {} | undefined; "header.skipLink": {} | undefined; "header.mainNav": {} | undefined; "header.homeLink": {} | undefined; "sitemap": {} | undefined; "prevNext.contenus": {} | undefined; "prevNext.precedent": {} | undefined; "prevNext.suivant": {} | undefined; "article.titre": {} | undefined; "article.tagline": {} | undefined; "article.published": { datetime: unknown; options: unknown; }; "meta.publication": {} | undefined; "meta.modification": {} | undefined; "meta.credit": {} | undefined; "fragments.titre": {} | undefined; "fragments.tagline": {} | undefined; "references.titre": {} | undefined; "references.slug": {} | undefined; "references.cta": {} | undefined; "references.tagline": {} | undefined; "veille.titre": {} | undefined; "veille.tagline": {} | undefined; "erreur.introuvable": {} | undefined; "erreur.autre": {} | undefined; "erreur.lienRetour": {} | undefined; "seo.meta.description": {} | undefined; "seo.article.title": {} | undefined; "seo.article.description": {} | undefined; "seo.code.title": {} | undefined; "seo.code.description": {} | undefined; "seo.references.title": {} | undefined; "seo.references.description": {} | undefined; "index.articles.pageName": {} | undefined; "index.articles.subtitle": {} | undefined; "index.fragments.pageName": {} | undefined; "index.fragments.subtitle": {} | undefined; "index.references.pageName": {} | undefined; "index.references.subtitle": {} | undefined; "index.veille.pageName": {} | undefined; "index.veille.subtitle": {} | undefined; "index.title": {} | undefined; "index.subtitle": {} | undefined; "index.quoi": {} | undefined; "index.comment": {} | undefined; "index.opensource": {} | undefined; "index.writing": {} | undefined; "index.latestProjects": {} | undefined; "index.latestArticles": {} | undefined; "index.allProjects": {} | undefined; "index.allArticles": {} | undefined; "index.latestSnippets": {} | undefined; "index.allSnippets": {} | undefined; "index.toc": {} | undefined; "contact.contenuVide": {} | undefined; } - -declare module "astro-i18n" { - export * from "astro-i18n/" - - export function l( - route: Uri | string & {}, - ...args: Uri extends keyof RouteParams - ? undefined extends RouteParams[Uri] - ? [params?: Record, targetLangCode?: LangCode, routeLangCode?: LangCode] - : [params: RouteParams[Uri], targetLangCode?: LangCode, routeLangCode?: LangCode] - : [params?: Record, targetLangCode?: LangCode, routeLangCode?: LangCode] - ): string - - export function t( - path: Path | string & {}, - ...args: undefined extends TranslationOptions[Path] - ? [options?: keyof TranslationOptions extends Path ? Record : TranslationOptions[Path], langCode?: LangCode] - : [options: TranslationOptions[Path], langCode?: LangCode] - ): string - - export function extractRouteLangCode(route: string): LangCode | undefined - - type Translation = string | { [translationKey: string]: string | Translation } - type Translations = { [langCode: string]: Record } - type RouteTranslations = { [langCode: string]: Record } - type InterpolationFormatter = (value: unknown, ...args: unknown[]) => string - class AstroI18n { - defaultLangCode: DefaultLangCode - supportedLangCodes: SupportedLangCode[] - showDefaultLangCode: boolean - translations: Translations - routeTranslations: RouteTranslations - get langCodes(): LangCode[] - get langCode(): LangCode - set langCode(langCode: LangCode) - get formatters(): Record - init(Astro: { url: URL }, formatters?: Record): void - addTranslations(translations: Translations): void - addRouteTranslations(routeTranslations: RouteTranslations): void - getFormatter(name: string): InterpolationFormatter | undefined - setFormatter(name: string, formatter: InterpolationFormatter): void - deleteFormatter(name: string): void - } - export const astroI18n: AstroI18n -} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3947946 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +**/*.d.ts +eslintrc-auto-import.mjs diff --git a/.prettierrc.mjs b/.prettierrc.mjs new file mode 100644 index 0000000..18563a5 --- /dev/null +++ b/.prettierrc.mjs @@ -0,0 +1,34 @@ +/** @type {import("prettier").Config} */ + +const config = { + arrowParens: 'always', + bracketSameLine: false, + bracketSpacing: true, + embeddedLanguageFormatting: 'auto', + endOfLine: 'lf', + htmlWhitespaceSensitivity: 'css', + insertPragma: false, + jsxSingleQuote: true, + printWidth: 80, + proseWrap: 'preserve', + quoteProps: 'as-needed', + requirePragma: false, + semi: false, + singleAttributePerLine: false, + singleQuote: true, + tabWidth: 2, + trailingComma: 'none', + useTabs: true, + vueIndentScriptAndStyle: false, + plugins: ['prettier-plugin-organize-imports', 'prettier-plugin-astro'], + overrides: [ + { + files: '*.astro', + options: { + parser: 'astro' + } + } + ] +} + +export default config diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100755 index d642209..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "command": "./node_modules/.bin/astro dev", - "name": "Development server", - "request": "launch", - "type": "node-terminal" - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json index 91789b7..28ac688 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,7 @@ { - "cssvar.files": [ - "./node_modules/open-props/open-props.min.css", - // if you have an alternative path to where your styles are located - // you can add it in this array of files - "assets/styles/variables.css" - ], - - // Do not ignore node_modules css files, which is ignored by default - "cssvar.ignore": [], - - // add support for autocomplete in JS or JS like files - "cssvar.extensions": [ - "css", "jsx", "tsx" - ], - "editor.formatOnSave": true -} \ No newline at end of file + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.insertSpaces": false, + "editor.detectIndentation": false, + "editor.tabSize": 2 +} diff --git a/astro.config.mjs b/astro.config.mjs index f3c1ce1..8bb12a7 100755 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -9,6 +9,10 @@ export default defineConfig({ site: "https://www.nardu.in", build: { format: "directory", + }, + i18n: { + locales: ["fr", "en"], + defaultLocale: "fr", }, image: { domains: ["assets.nardu.in"], diff --git a/astro.i18n.config.ts b/astro.i18n.config.ts deleted file mode 100755 index f349767..0000000 --- a/astro.i18n.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { defineAstroI18nConfig } from "astro-i18n"; - -export default defineAstroI18nConfig({ - defaultLangCode: "fr", - supportedLangCodes: ["en"], - showDefaultLangCode: false, - trailingSlash: "never", - translations: { - fr: "src/i18n/fr.json", - en: "src/i18n/en.json", - }, - routeTranslations: { - en: { - "sci-hub-blocage": "sci-hub-unblock", - fragments: "snippets", - "plan-du-site": "sitemap", - references: "work", - }, - }, -}); diff --git a/bun.lockb b/bun.lockb index 6519f63..44152a4 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 960bd98..01a8606 100755 --- a/package.json +++ b/package.json @@ -16,11 +16,15 @@ "@astrojs/mdx": "4.0.3", "@astrojs/rss": "4.0.10", "@astrojs/sitemap": "3.2.1", + "@astrojs/ts-plugin": "^1.10.4", "astro": "5.1.1", - "sharp": "^0.33.4" + "sharp": "^0.33.5" }, "devDependencies": { - "autoprefixer": "^10.4.19", - "postcss": "^8.4.38" + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "prettier": "^3.4.2", + "prettier-plugin-astro": "^0.14.1", + "prettier-plugin-organize-imports": "^4.1.0" } } diff --git a/src/components/LangSwitcher.astro b/src/components/LangSwitcher.astro index 9af34e5..cbdaee8 100755 --- a/src/components/LangSwitcher.astro +++ b/src/components/LangSwitcher.astro @@ -1,38 +1,12 @@ --- -import { l, astroI18n } from "astro-i18n"; - -// get all the locales available on the website and remove the one currently in use -const availableLocales = astroI18n.langCodes.filter( - (locale) => locale !== astroI18n.langCode -); -// current path -const currentRoute = Astro.url.pathname; - -function localeName(locale) { - let localeName = ""; - switch (locale) { - case "fr": - localeName = "Français"; - break; - case "en": - localeName = "English"; - break; - } - return localeName; -} +import { languages } from '../i18n/ui' --- -
    +
      { - // create a list of available alternative locale - availableLocales.map((locale) => ( + Object.entries(languages).map(([lang, label]) => (
    • - - {localeName(locale)} - + {label}
    • )) } diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts new file mode 100644 index 0000000..e83786c --- /dev/null +++ b/src/i18n/ui.ts @@ -0,0 +1,150 @@ +export const languages = { + en: 'English', + fr: 'Français' +} + +export const defaultLang = 'fr' + +export const ui = { + en: { + accueil: 'home', + tagline: 'Freelance web developer specialized in accessibility.', + copyright: '(re)Made with Astro', + contact: { + title: 'contact', + email: 'Send me an email (open in application).', + tel: 'Call or text me (open in application).', + contenuVide: 'Soon: really nice content.' + }, + header: { + skipLink: 'Skip to content', + mainNav: 'Main menu', + homeLink: 'Back to homepage' + }, + sitemap: 'Site map', + prevNext: { + contenus: 'Similar content', + precedent: 'Previous', + suivant: 'Next' + }, + article: { + titre: 'articles', + tagline: 'I blog, sometimes.', + published: 'Published on {datetime|date(options)}' + }, + meta: { + publication: 'Published on', + modification: 'Last updated on', + credit: 'Image by' + }, + fragments: { + titre: 'snippets', + tagline: 'School with Nicool.' + }, + references: { + titre: 'work', + slug: 'work', + cta: 'Visit website', + tagline: 'Some work.' + }, + veille: { + titre: 'Around the web', + tagline: 'Some links that interested me.' + }, + erreur: { + introuvable: 'Sorry, page not found.', + autre: 'Oups… sorry about that.', + lienRetour: 'Back to the home page' + }, + seo: { + meta: { + description: + 'Web developer specialized in accessibility and eco-design in Toulouse, France. Development of custom websites, RGAA compliance, maintenance, etc.' + }, + article: { + title: 'Articles', + description: + 'A few articles about graphic design and front-end development.' + }, + code: { + title: 'Snippets', + description: 'Snippets of fresh, easy and accessible code.' + }, + references: { + title: 'Work', + description: 'A few case studies I worked on as a front-end developer.' + } + } + }, + fr: { + accueil: 'accueil', + tagline: 'Développeur web spécialisé en accessibilité.', + copyright: '(re)Fait avec Astro', + contact: { + title: 'contact', + email: 'Envoyez-moi un mail (ouverture du logiciel automatique).', + tel: 'Contactez-moi par téléphone (ouverture du logiciel automatique).' + }, + contenuVide: 'Bientôt ici : du contenu de qualité', + header: { + skipLink: 'Accéder au contenu', + mainNav: 'Menu principal', + homeLink: 'Accueil du site' + }, + sitemap: 'Plan du site', + prevNext: { + contenus: 'Contenus similaires', + precedent: 'Précédent', + suivant: 'Suivant' + }, + article: { + titre: 'articles', + tagline: 'Je blog, un peu.', + published: 'Publié le {datetime|date(options)}' + }, + meta: { + publication: 'Publié le', + modification: 'Mis à jour le', + credit: 'Image par' + }, + fragments: { + titre: 'fragments', + tagline: 'Les tutos de Nico mdr.' + }, + references: { + titre: 'références', + slug: 'references', + cta: 'Consulter le site', + tagline: 'Quelques références.' + }, + veille: { + titre: 'veille', + tagline: 'Des liens, en vrac.' + }, + erreur: { + introuvable: 'Page introuvable', + autre: 'Oups… désolé pour cette erreur.', + lienRetour: 'Retour à l’accueil' + }, + seo: { + meta: { + description: + 'Développeur web spécialisé en accessibilité numérique et éco-conception à Toulouse. Création de sites web sur mesure, mise en conformité RGAA, maintenance, etc.' + }, + article: { + title: 'Articles', + description: + "Quelques articles sur le développement web front-end et l'informatique à Toulouse." + }, + code: { + title: 'Fragments', + description: 'Fragments de codes stylés, faciles et accessibles.' + }, + references: { + title: 'Références', + description: + 'Quelques travaux réalisés en tant que et développeur web front-end à Toulouse.' + } + } + } +} as const diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 0fd0d5e..6ea25eb 100755 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,6 +1,5 @@ --- -import { astroI18n } from "astro-i18n"; -astroI18n.init(Astro); +const locale = Astro.currentLocale; import "../styles/style.css"; @@ -11,7 +10,7 @@ import Footer from "../components/Footer.astro"; const { pageTitle } = Astro.props; --- - +
      diff --git a/src/layouts/MarkdownPostLayout.astro b/src/layouts/MarkdownPostLayout.astro index eb46a29..8e747d9 100755 --- a/src/layouts/MarkdownPostLayout.astro +++ b/src/layouts/MarkdownPostLayout.astro @@ -1,33 +1,27 @@ --- -import { l, t, astroI18n } from "astro-i18n"; -// import AstroImage from "../components/AstroImage.astro"; -import BaseLayout from "../layouts/BaseLayout.astro"; +import BaseLayout from '../layouts/BaseLayout.astro' +import { getLangFromUrl, useTranslations } from '../utils/i18n' -const { frontmatter, image, title } = Astro.props; -const publishedDate = new Date(frontmatter.pubDate); -const localizedDate = new Intl.DateTimeFormat(astroI18n.langCode, { - dateStyle: "long", -}).format(publishedDate); +const locale = getLangFromUrl(Astro.url) +const t = useTranslations(locale) + +const { frontmatter, image, title } = Astro.props +const publishedDate = new Date(frontmatter.pubDate) +const localizedDate = new Intl.DateTimeFormat(locale, { + dateStyle: 'long' +}).format(publishedDate) ---

      - Publié le :

      -

      - { - t("article.published", { - datetime: frontmatter.pubDate, - options: { dateStyle: "long" }, - }) - } -

      -
      +
      { frontmatter.tags.map((tag) => ( -

      +

      {tag}

      )) diff --git a/src/pages/index.astro b/src/pages/index.astro index 7382c51..340c8b9 100755 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,8 +1,5 @@ --- -// init i18n -import { getLocale } from "astro-i18n-aut"; - -const locale = getLocale(Astro.url); +const locale = Astro.currentLocale; // import stuff import BaseLayout from "../layouts/BaseLayout.astro"; diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..0b3fc69 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,28 @@ +import { defaultLang, ui } from '../i18n/ui' + +export function getLangFromUrl(url: URL) { + const [, lang] = url.pathname.split('/') + if (lang in ui) return lang as keyof typeof ui + return defaultLang +} + +type NestedKeyOf = { + [K in keyof T]: T[K] extends object + ? `${K & string}.${NestedKeyOf & string}` + : K & string +}[keyof T] + +export function useTranslations(lang: keyof typeof ui) { + return function t(key: NestedKeyOf<(typeof ui)[typeof defaultLang]>) { + const keys = key.split('.') + let value = ui[lang] + let fallback = ui[defaultLang] + + for (const k of keys) { + value = value?.[k] + fallback = fallback?.[k] + } + + return value || fallback + } +} diff --git a/tsconfig.json b/tsconfig.json index e71eb5a..fb16021 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,18 @@ { - "extends": "astro/tsconfigs/base", - "include": [".astro/types.d.ts", "**/*"], + "extends": "astro/tsconfigs/base", + "include": [".astro/types.d.ts", "**/*"], "exclude": ["dist"], - "compilerOptions": { - "strictNullChecks": true - } + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@components/*": ["src/components/*"], + "@layouts/*": ["src/layouts/*"] + }, + "strictNullChecks": true, + "plugins": [ + { + "name": "@astrojs/ts-plugin" + } + ] + } }