Skip to content

Commit

Permalink
Add i18n framework and extract hard coded strings
Browse files Browse the repository at this point in the history
  • Loading branch information
trishrempel committed Jun 12, 2023
1 parent 9837412 commit b18dc2e
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 51 deletions.
125 changes: 125 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"i18next": "^22.5.1",
"i18next-browser-languagedetector": "^7.0.2",
"i18next-http-backend": "^2.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
Expand Down
14 changes: 14 additions & 0 deletions public/locales/ar/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"label-amount": "أدخل مبلغًا:",
"label-currency": "أدخل عملة:",
"label-date": "أدخل تاريخًا:",
"label-formatted-amount": "المبلغ المنسق:",
"label-formatted-currency": "العملة المنسقة:",
"label-formatted-date": "التاريخ المنسق:",
"label-formatted-quantity": "الكمية المنسقة:",
"label-locale": "أدخل لغة:",
"label-quantity": "أدخل كمية:",
"label-formatted-file-type": "نوع الملف المنسق:",
"label-file-type": "حدد نوع الملف:",
"heading": "التدويل للجميع"
}
14 changes: 14 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"heading": "Internationalization is for Everyone",
"label-locale": "Enter a locale:",
"label-date": "Enter a date:",
"label-formatted-date": "Formatted date:",
"label-currency": "Enter a currency:",
"label-quantity": "Enter a quantity:",
"label-formatted-quantity": "Formatted quantity:",
"label-amount": "Enter an amount:",
"label-formatted-amount": "Formatted amount:",
"label-formatted-currency": "Formatted currency:",
"label-file-type": "Select a file type:",
"label-formatted-file-type": "Formatted file type:"
}
14 changes: 14 additions & 0 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"label-amount": "Saisissez un montant :",
"label-currency": "Saisissez une devise :",
"label-date": "Saisissez une date :",
"label-formatted-amount": "Montant formaté :",
"label-formatted-currency": "Devise formatée :",
"label-formatted-date": "Date formatée :",
"label-formatted-quantity": "Quantité formatée :",
"label-locale": "Saisissez un paramètre régional :",
"label-quantity": "Saisissez une quantité :",
"label-formatted-file-type": "Type de fichier formaté :",
"label-file-type": "Sélectionnez un type de fichier :",
"heading": "L'internationalisation est pour tout le monde"
}
133 changes: 88 additions & 45 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import "./App.css";
import React, { useEffect, useState, useCallback, useMemo } from "react";
import React, {
useEffect,
useState,
useCallback,
useMemo,
Suspense,
} from "react";
import { useTranslation } from "react-i18next";
import LoadingSpinner from "./components/LoadingSpinner";

const FILE_TYPES = ["file", "image", "video"];

function App() {
const { t, i18n } = useTranslation();
const [formattedFileType, setFormattedFileType] = useState("");
const [formattedDate, setFormattedDate] = useState("");
const [formattedQuantity, setFormattedQuantity] = useState("");
Expand Down Expand Up @@ -34,6 +43,15 @@ function App() {
updateFormattedAmount();
}, [amount, currency, updateFormattedAmount]);

const handleLocaleChange = (e) => {
i18n.changeLanguage(e.target.value);
setFormattedFileType("");
setFormattedDate("");
setFormattedQuantity("");
setFormattedAmount("");
setFormattedCurrency("");
};

const handleFileTypeChange = (e) => {
const fileType = e.target.value;
setFormattedFileType(`The ${fileType} is ready.`);
Expand Down Expand Up @@ -74,50 +92,75 @@ function App() {
};

return (
<div className="App">
<header className="App-header">
<h1>Internationalization is for Everyone</h1>
<div className="form">
<label htmlFor="file-type">Select a file type:</label>
<select
name="file-type"
id="file-type"
onChange={handleFileTypeChange}
>
{FileTypeOptions}
</select>
<label htmlFor="formatted-file-type">Formatted file type:</label>
<div id="formatted-file-type">{formattedFileType}</div>
<label htmlFor="date">Enter a date:</label>
<input id="date" type="date" onChange={handleDateChange} />
<label htmlFor="formatted-date">Formatted date:</label>
<div id="formatted-date">{formattedDate}</div>
<label htmlFor="quantity">Enter a quantity:</label>
<input id="quantity" type="number" onChange={handleQuantityChange} />
<label htmlFor="formatted-quantity">Formatted quantity:</label>
<div id="formatted-quantity">{formattedQuantity}</div>
<label htmlFor="currency">Select a currency:</label>
<select name="currency" id="currency" onChange={handleCurrencyChange}>
<option value="USD">US Dollar (USD)</option>
<option value="EUR">Euro (EUR)</option>
<option value="JPY">Japanese Yen (JPY)</option>
</select>
<label htmlFor="amount">Enter an amount:</label>
<input id="amount" type="number" onChange={handleAmountChange} />
<label htmlFor="formatted-amount">Formatted amount:</label>
<div id="formatted-amount">{formattedAmount}</div>
<label htmlFor="formatted-currency">Formatted currency:</label>
<div id="formatted-currency">{formattedCurrency}</div>
</div>
<p>
Slide deck available{" "}
<a className="App-link" href="https://bit.ly/prdc-i18n">
here
</a>
.
</p>
</header>
</div>
<Suspense fallback={LoadingSpinner}>
<div className="App" dir={i18n.dir()}>
<header className="App-header">
<h1>{t("heading")}</h1>
<div className="form">
<label htmlFor="locale">{t("label-locale")}</label>
<input
id="locale"
type="text"
onChange={handleLocaleChange}
defaultValue={i18n.language}
/>
<label htmlFor="file-type">{t("label-file-type")}</label>
<select
name="file-type"
id="file-type"
onChange={handleFileTypeChange}
>
{FileTypeOptions}
</select>
<label htmlFor="formatted-file-type">
{t("label-formatted-file-type")}
</label>
<div id="formatted-file-type">{formattedFileType}</div>
<label htmlFor="date">{t("label-date")}</label>
<input id="date" type="date" onChange={handleDateChange} />
<label htmlFor="formatted-date">{t("label-formatted-date")}</label>
<div id="formatted-date">{formattedDate}</div>
<label htmlFor="quantity">{t("label-quantity")}</label>
<input
id="quantity"
type="number"
onChange={handleQuantityChange}
/>
<label htmlFor="formatted-quantity">
{t("label-formatted-quantity")}
</label>
<div id="formatted-quantity">{formattedQuantity}</div>
<label htmlFor="currency">{t("label-currency")}</label>
<select
name="currency"
id="currency"
onChange={handleCurrencyChange}
>
<option value="USD">US Dollar (USD)</option>
<option value="EUR">Euro (EUR)</option>
<option value="JPY">Japanese Yen (JPY)</option>
</select>
<label htmlFor="amount">{t("label-amount")}</label>
<input id="amount" type="number" onChange={handleAmountChange} />
<label htmlFor="formatted-amount">
{t("label-formatted-amount")}
</label>
<div id="formatted-amount">{formattedAmount}</div>
<label htmlFor="formatted-currency">
{t("label-formatted-currency")}
</label>
<div id="formatted-currency">{formattedCurrency}</div>
</div>
<p>
Slide deck available{" "}
<a className="App-link" href="https://bit.ly/prdc-i18n">
here
</a>
.
</p>
</header>
</div>
</Suspense>
);
}

Expand Down
Loading

0 comments on commit b18dc2e

Please sign in to comment.