Skip to content

Commit

Permalink
Add multilanguage support (#1)
Browse files Browse the repository at this point in the history
* add multilanguage support

* update de locales

* update en locales

* update locales

* minor improvments

* add favicon

* update readme

* update readme

* add dev script
  • Loading branch information
leneffets authored Nov 28, 2024
1 parent f435a6e commit 56fccef
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 153 deletions.
14 changes: 14 additions & 0 deletions .devcontainer/lighttpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
server.document-root = "/workspaces/currency"

server.port = 3000
index-file.names = ( "index.html" )

# If running lighttpd earlier than lighttpd 1.4.71, uncomment (remove '#') to add the following:
mimetype.assign = (
".html" => "text/html",
".txt" => "text/plain",
".jpg" => "image/jpeg",
".png" => "image/png",
".js" => "application/javascript",
".css" => "text/css"
)
9 changes: 9 additions & 0 deletions .devcontainer/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

# run as root

apt-get update
apt-get install -y lighttpd
apt-get clean

lighttpd -f lighttpd.conf
57 changes: 48 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,65 @@
# Currency and Weight Converter

A simple web application to convert prices between currencies and calculate price per weight. The app supports:
- Live exchange rate updates.
- Calculations for total price, price per kilogram, and custom unit prices.
- Multiple currencies: PLN, CZK, EUR, TRY, GBP.
1. **Currency Conversion**:
- Convert prices from one currency to another.
- Supports the following currencies:
- PLN (Polish Zloty)
- USD (US Dollar)
- EUR (Euro)
- JPY (Japanese Yen)
- CHF (Swiss Franc)
- GBP (British Pound)
- CZK (Czech Koruna)
- DKK (Danish Krone)
- TRY (Turkish Lira)
- SEK (Swedish Krona)
- NOK (Norwegian Krone)

1. **Exchange Rate Updates**:
- Uses real api endpoint (`https://api.exchangerate-api.com/v4/latest/`) to get latest exchange rates
- Displays the last updated time for the exchange rate.

1. **Weight-Based Price Calculations**:
- Calculate price per kilogram for a given weight.
- Calculate price for a specific unit weight (e.g., 250g).
- For example: compare prices in supermarket:
* enter price for 200g in PLN
* converts to kilogram price in EUR
* converts to 250g price in EUR

1. **Localization**:
- Automatically detects browser language and switches between English and German.
- Localization data is stored in separate JSON files (`locales/en.json` and `locales/de.json`).

1. **Settings Persistence**:
- Saves selected source and target currencies in the browser using `localStorage`.
- Restores saved settings when the page is reloaded.

1. **Responsive Design**:
- The application works seamlessly on both desktop and mobile devices.

## How to Use
1. Select the **current currency** and the **target currency**.
2. Enter the **price** in the current currency.
3. (Optional) Add the product's **weight** and a **custom unit weight** (e.g., 250g).
4. The app will calculate:
1. Enter the **price** in the current currency.
1. (Optional) Add the product's **weight** and a **custom unit weight** (e.g., 250g).
1. The app will calculate:
- Price in the target currency.
- Price per kilogram (if weight is provided).
- Price for the specified unit (if unit weight is provided).
5. Click the 🔄 button to fetch the latest exchange rates.
- Price for the specified unit in **target currency** (if unit weight is provided).
1. Click the 🔄 button to fetch the latest exchange rates.

Access the app directly from GitHub Pages:
👉 [Currency and Weight Converter](https://leneffets.github.io/currency/)

## Screenshot
![image](https://github.com/user-attachments/assets/a1d71a72-45cc-4436-a050-f4c4cbb8373b)

## Development Setup

1. Clone the repository:
```bash
git clone https://github.com/leneffets/currency.git
```

## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
Expand Down
Binary file added favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
159 changes: 15 additions & 144 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,17 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Currency and Weight Converter</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f4;
}
.container {
max-width: 600px;
margin: auto;
padding: 20px;
background: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
label {
display: block;
margin: 10px 0 5px;
}
input, button, select {
width: calc(100% - 20px);
padding: 10px;
margin: 5px 0 15px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
.exchange-container {
display: flex;
align-items: center;
}
#exchangeRate {
flex: 1;
}
.refresh-button {
background: none;
border: none;
cursor: pointer;
font-size: 20px;
color: #007bff;
margin-left: 10px;
padding: 0;
height: auto;
width: auto;
}
.refresh-button:hover {
color: #0056b3;
}
button {
background-color: #28a745;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
.output {
font-weight: bold;
}
.exchange-info {
font-size: 0.9em;
color: gray;
}
</style>
<link rel="stylesheet" type="text/css" href="styles.css">
<link rel="icon" type="image/png" href="favicon.png"/>
<script src="script.js"></script>

</head>
<body>
<div class="container">
<h1>Currency and Weight Converter</h1>
<label for="sourceCurrency">Current currency:</label>
<select id="sourceCurrency">
<h1 id="title"></h1>

<label for="sourceCurrency" id="sourceLabel"></label>
<select id="sourceCurrency" onchange="saveCurrencySettings(); updateExchangeRate(); performCalculations();">
<option value="PLN" selected>PLN (Polish Zloty)</option>
<option value="USD">USD (US Dollar)</option>
<option value="EUR">EUR (Euro)</option>
Expand All @@ -87,8 +28,8 @@ <h1>Currency and Weight Converter</h1>
<option value="NOK">NOK (Norwegian Krone)</option>
</select>

<label for="targetCurrency">Target currency:</label>
<select id="targetCurrency">
<label for="targetCurrency" id="targetLabel"></label>
<select id="targetCurrency" onchange="saveCurrencySettings(); updateExchangeRate(); performCalculations();">
<option value="EUR" selected>EUR (Euro)</option>
<option value="PLN">PLN (Polish Zloty)</option>
<option value="USD">USD (US Dollar)</option>
Expand All @@ -102,93 +43,23 @@ <h1>Currency and Weight Converter</h1>
<option value="NOK">NOK (Norwegian Krone)</option>
</select>

<label id="priceLabel" for="price">Price in current currency:</label>
<label for="price" id="priceLabel"></label>
<input type="number" id="price" placeholder="e.g. 10" step="0.01" oninput="performCalculations()">

<label for="weight">Weight in grams (optional):</label>
<label for="weight" id="weightLabel"></label>
<input type="number" id="weight" placeholder="e.g. 200" step="0.01" oninput="performCalculations()">

<label for="unitWeight">Unit weight in grams (optional):</label>
<label for="unitWeight" id="unitWeightLabel"></label>
<input type="number" id="unitWeight" placeholder="e.g. 250" step="0.01" oninput="performCalculations()">

<label for="exchangeRate">Current exchange rate:</label>
<label for="exchangeRate" id="exchangeRateLabel"></label>
<div class="exchange-container">
<input type="text" id="exchangeRate" readonly>
<button class="refresh-button" id="refreshRate" title="Update exchange rate">🔄</button>
<button class="refresh-button" id="refreshRate" title="Update exchange rate" onclick="updateExchangeRate()">🔄</button>
</div>
<div class="exchange-info" id="exchangeInfo"></div>

<div class="output" id="output"></div>
</div>

<script>
let exchangeRate = 0.22; // Example value
let exchangeTimestamp = '';

// Fetch exchange rate
async function fetchExchangeRate() {
const sourceCurrency = document.getElementById('sourceCurrency').value;
const targetCurrency = document.getElementById('targetCurrency').value;

try {
const response = await fetch(`https://api.exchangerate-api.com/v4/latest/${sourceCurrency}`);
const data = await response.json();
exchangeRate = data.rates[targetCurrency];
exchangeTimestamp = data.time_last_updated
? new Date(data.time_last_updated * 1000).toLocaleString()
: 'Unknown';

// Display exchange rate and time
document.getElementById('exchangeRate').value = `1 ${sourceCurrency} = ${exchangeRate.toFixed(4)} ${targetCurrency}`;
document.getElementById('exchangeInfo').textContent = `Last updated: ${exchangeTimestamp}`;
performCalculations(); // Recalculate after rate update
} catch (error) {
alert('Error fetching exchange rate.');
}
}

// Update exchange rate with refresh button
document.getElementById('refreshRate').addEventListener('click', fetchExchangeRate);

// Update "Price in current currency" label dynamically
document.getElementById('sourceCurrency').addEventListener('change', () => {
const sourceCurrency = document.getElementById('sourceCurrency').value;
document.getElementById('priceLabel').textContent = `Price in ${sourceCurrency}:`;
fetchExchangeRate();
});

// Perform calculations
function performCalculations() {
const priceInSource = parseFloat(document.getElementById('price').value);
const weightInGrams = parseFloat(document.getElementById('weight').value);
const unitWeight = parseFloat(document.getElementById('unitWeight').value);
const sourceCurrency = document.getElementById('sourceCurrency').value;
const targetCurrency = document.getElementById('targetCurrency').value;

if (isNaN(priceInSource) || priceInSource <= 0) {
document.getElementById('output').innerHTML = 'Please enter a valid price.';
return;
}

const priceInTarget = priceInSource * exchangeRate;
let output = `Price ${priceInSource} ${sourceCurrency}: ${priceInTarget.toFixed(2)} ${targetCurrency}`;

// Only calculate weight-based values if weight is provided
if (!isNaN(weightInGrams) && weightInGrams > 0) {
const pricePerKg = (priceInTarget / weightInGrams) * 1000;
output += `<br>Price per kilogram: ${pricePerKg.toFixed(2)} ${targetCurrency}/kg`;

if (!isNaN(unitWeight) && unitWeight > 0) {
const priceForUnit = (pricePerKg / 1000) * unitWeight;
output += `<br>Price for ${unitWeight}g: ${priceForUnit.toFixed(2)} ${targetCurrency}`;
}
}

document.getElementById('output').innerHTML = output;
}

// Fetch exchange rate on page load
fetchExchangeRate();
</script>
</body>
</html>
14 changes: 14 additions & 0 deletions locales/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "Währungs- und Gewichtsumrechner",
"sourceLabel": "Quellwährung:",
"targetLabel": "Zielwährung:",
"priceLabel": "Preis in aktueller Währung:",
"weightLabel": "Gewicht in Gramm in Quellwährung (optional):",
"unitWeightLabel": "Gewicht in Gramm in Zielwährung (optional):",
"exchangeRateLabel": "Wechselkurs:",
"convertedPrice": "Preis {price} {sourceCurrency}: {convertedPrice} {targetCurrency}",
"pricePerKg": "Preis pro Kilogram: {pricePerKg} {targetCurrency}/kg",
"unitPrice": "Preis für {unitWeight}g: {unitPrice} {targetCurrency}",
"lastUpdated": "Zuletzt aktualisiert: {exchangeTimestamp}",
"errorFetchingRate": "Wechselkurs konnte nicht abgerufen werden. Bitte versuchen Sie es später erneut."
}
14 changes: 14 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "Currency and Weight Converter",
"sourceLabel": "Source Currency:",
"targetLabel": "Target Currency:",
"priceLabel": "Price in current currency:",
"weightLabel": "Weight in grams for Source Currency (optional):",
"unitWeightLabel": "Weight in grams for Target Currency (optional):",
"exchangeRateLabel": "Exchange Rate:",
"convertedPrice": "Price {price} {sourceCurrency}: {convertedPrice} {targetCurrency}",
"pricePerKg": "Price per kilogram: {pricePerKg} {targetCurrency}/kg",
"unitPrice": "Price for {unitWeight}g: {unitPrice} {targetCurrency}",
"lastUpdated": "Last updated: {exchangeTimestamp}",
"errorFetchingRate": "Unable to fetch the exchange rate. Please try again later."
}
Loading

0 comments on commit 56fccef

Please sign in to comment.