Currency Converter

Configuration

Configurer un projet tutoriel

Introduction

Ceci est un guide de tutoriel plus approfondi sur la façon de configurer un projet NextJS très simple en utilisant gt-next. Nous vous accompagnerons du début à la fin, y compris la configuration du projet puis sa traduction. Au cours de ce tutoriel, nous passerons de concepts simples à plus avancés. Ce tutoriel suppose que vous avez une compréhension générale de Typescript, Next.js et React.

Voici une liste des éléments que nous couvrirons dans ce tutoriel :

  • Configuration d'un nouveau projet Next.js
  • Utilisation du composant <T> pour traduire une application
  • Utilisation de composants variables comme <Var>, <Currency>, <DateTime>, et <Num> pour traduire du contenu dynamique
  • Utilisation de composants de branche comme <Plural>, et <Branch> pour traduire du contenu conditionnel
  • Utilisation du routage i18n dans votre application

Notre application sera une application simple qui nous permettra de vérifier le taux de conversion entre les devises. Nous n'utiliserons que le style en ligne et uniquement la bibliothèque gt-next pour garder les choses aussi simples que possible. Cet exemple a été construit sur la base du tutoriel Currency Converter sur GeeksforGeeks.

Configurez Votre Application Next

Tout d'abord, créons une nouvelle application NextJS. Vous pouvez le faire en exécutant la commande suivante :

npx create-next-app@latest

Cela vous mènera à l'assistant de configuration, où vous pouvez choisir le nom de votre application et le modèle que vous souhaitez utiliser. Pour ce tutoriel, utilisez le nom currencies et sélectionnez Oui lorsqu'on vous demande si vous souhaitez utiliser TypeScript.

Naviguez vers le répertoire du projet, et démarrons l'application !

cd currencies
npm install
npm run dev

Cela démarrera l'application sur http://localhost:3000.

Ajoutons du contenu !

Maintenant que notre application est configurée, remplaçons le contenu de notre application pour afficher un simple convertisseur de devises. Il suffit de copier et coller le code suivant dans les fichiers src/app/page.tsx et src/app/layout.tsx.

Ne vous inquiétez pas trop de son fonctionnement pour l'instant. Tout ce code fait est de simuler une récupération à une API de change de devises et d'afficher le taux de change entre deux devises.

src/app/page.tsx
"use client";

import { useEffect, useState, useCallback } from "react";

// A map between two currencies and their exchange rate (from -> to)
type ExchTable = Record<string, Record<string, number>>;

const EXCH_RATES: ExchTable = {
  usd: { usd: 1, inr: 73.5, eur: 0.85, jpy: 105.45, gbp: 0.72 },
  inr: { usd: 0.014, inr: 1, eur: 0.012, jpy: 1.46, gbp: 0.01 },
  eur: { usd: 1.18, inr: 85.5, eur: 1, jpy: 123.5, gbp: 0.85 },
  jpy: { usd: 0.0095, inr: 0.68, eur: 0.0081, jpy: 1, gbp: 0.0068 },
  gbp: { usd: 1.39, inr: 99.5, eur: 1.17, jpy: 146.5, gbp: 1 },
};

// some styles for button
const buttonStyle = {
  backgroundColor: "#007bff",
  color: "white",
  border: "none",
  padding: "10px 20px",
  cursor: "pointer",
  borderRadius: "5px",
  fontSize: "16px",
  margin: "20px",
};

/**
 * This function is meant to simulate an api fetch request to get the current exchange.
 * Waits for 1 second before returning the exchange rate.
 * @returns the exchange rate between two currencies
 */
async function fetchExchangeRate(from: string, to: string): Promise<number> {
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return EXCH_RATES[from][to];
}

function Page() {
  // exch rates
  const [info, setInfo] = useState<ExchTable>({});
  const options = ["usd", "inr", "eur", "jpy", "gbp"];

  // currencies
  const [from, setFrom] = useState("usd");
  const [to, setTo] = useState("inr");

  // values
  const [input, setInput] = useState(0);
  const [output, setOutput] = useState(0);

  // Function to convert the currency
  const convert = useCallback(() => {
    if (info?.[from]?.[to]) {
      const rate = info[from][to];
      setOutput(input * rate);
    } else {
      setOutput(0);
    }
  }, [info, input, to, from]);

  // Calling the api whenever from or to currency changes
  useEffect(() => {
    // If the exchange rate is already present, then convert
    if (info?.[from]?.[to]) {
      convert();
      return;
    }
    // Fetch the exchange rate
    (async () => {
      const response = await fetchExchangeRate(from, to);
      // Enter new response without overwriting old info
      setInfo((prevInfo) => ({
        ...prevInfo,
        [from]: {
          ...(prevInfo?.[from] || undefined),
          [to]: response,
        },
      }));
    })();
  }, [from, to, convert, info]);

  // Call convert whenever a user switches the currency
  useEffect(() => {
    convert();
  }, [info, convert]);

  // Function to switch between two currency
  function flip() {
    const temp = from;
    setFrom(to);
    setTo(temp);
  }

  return (
    <div style={{ margin: "0 auto", width: "50%", textAlign: "center" }}>
      <div style={{ margin: "20px 0", paddingBottom: "20px" }}>
        <h1 style={{ fontSize: "2.5em", fontWeight: "bold" }}>
          Convertisseur de devises
        </h1>
      </div>
      <div style={{ flex: 2, textAlign: "center", margin: "20px 0" }}>
        <h3>Montant</h3>
        <input
          type="text"
          placeholder="Entrez le montant"
          style={{ textAlign: "center" }}
          onChange={(e) => {
            setInput(Number(e.target.value));
          }}
        />
      </div>
      <div
        style={{ display: "flex", justifyContent: "center", margin: "20px 0" }}
      >
        <div style={{ flex: 1, textAlign: "center" }}>
          <label htmlFor="from">
            <h3>De</h3>
          </label>
          <select
            name="from"
            id="from"
            value={from}
            onChange={(e) => setFrom(e.target.value)}
          >
            {options.map((option) => (
              <option key={option} value={option}>
                {option.toUpperCase()}
              </option>
            ))}
          </select>
        </div>
        <div style={{ flex: 1, textAlign: "center" }}>
          <button
            onClick={() => {
              flip();
            }}
            style={buttonStyle}
          >
            Échanger
          </button>
        </div>
        <div style={{ flex: 1, textAlign: "center" }}>
          <label htmlFor="to">
            <h3>À</h3>
          </label>
          <select
            name="to"
            id="to"
            value={to}
            onChange={(e) => setTo(e.target.value)}
          >
            {options.map((option) => (
              <option key={option} value={option}>
                {option.toUpperCase()}
              </option>
            ))}
          </select>
        </div>
      </div>
      <div style={{ margin: "0 auto", width: "50%", textAlign: "center" }}>
        <button
          onClick={() => {
            convert();
          }}
          style={buttonStyle}
        >
          Convertir
        </button>
        <h2>Montant Converti :</h2>
        <p>{input + " " + from + " = " + output.toFixed(2) + " " + to}</p>
      </div>
    </div>
  );
}

export default Page;
src/app/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Currency Converter",
  description: "A simple currency converter",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        {children}
      </body>
    </html>
  );
}

Conclusion

Vous avez maintenant une application NextJS normale configurée et prête à être traduite en utilisant gt-next.

Comment trouvez-vous ce guide ?