Skip to content

Jyyunrin/group5_softwareengineering

Repository files navigation

FANGO

A just-in-time language companion for real-world travel.

Python Django React OpenAI


πŸ“˜ Table of Contents


🌍 Overview

FANGO is a just-in-time language companion built for travellers. Snap a photo of anythingβ€”street food, a monument, a cafΓ© menuβ€”and FANGO instantly:

  • Recognizes the object
  • Translates it into your chosen language
  • Pronounces it for you
  • Provides two safe, usable phrases
  • Saves everything for later review

Unlike lesson-based apps, FANGO starts with the real world in front of you.


✨ Features

πŸ” Instant Photo-to-Translation

  • Upload or take a photo
  • AI-powered object detection
  • Real-time translation
  • Auto-generated pronunciation
  • Auto-generated travel-safe short phrases

🧳 Travel-Focused

  • Designed for situations when you need answers now
  • Helpful for food, signs, labels, products, monuments, etc.

πŸ—‚οΈ Smart History Tracking

  • Review previous translations
  • Learn vocabulary naturally
  • Pagination and filtering

πŸ‘€ Accounts & Sync

  • Create/manage user account
  • Data synced across devices
  • JWT authentication

πŸŽ“ Micro-Learning

  • Learn during travel moments
  • No long lessons
  • Safe, consistent phrasing

🧰 Tech Stack

Backend

  • Python 3.12
  • Django 5.2
  • Django REST Framework
  • PostgreSQL
  • Redis
  • JWT Auth (SimpleJWT)
  • Gunicorn
  • Pillow (image processing)
  • OpenAI Vision + GPT translation

Frontend

  • React
  • TypeScript
  • HTML / CSS
  • Axios
  • Vite

AI

  • OpenAI Vision API (Object detection from image)
  • GPT for translations, pronunciation, phrase generation

πŸ—οΈ Architecture

Frontend (React/TS)
      ↓ API calls
Backend (Django REST Framework)
      ↓
OpenAI Vision API β†’ Detect object
      ↓
GPT β†’ Translate + Pronounce + Generate phrases
      ↓
PostgreSQL (store history, user data)

βš™οΈ Installation

Backend Setup

Ensure docker is installed.

git pull

Copy .env.example contents to local .env and fill in respective values.

Change directory to project root:

cd ../group5_softwareengineering/

First time running:

docker compose up --build

Remember to makemigrations if schema changed with:

docker compose run django-web python manage.py makemigrations

docker compose run django-web python manage.py migrate

Also, run the following to insert the language mock data:

docker compose run -it django-web python manage.py shell

exec(open("fango/insert_mock_languages.py").read())

exit()

Starting container after first time:

Start services in .docker-compose.yml in -d detached mode, which runs containers in background

docker compose up -d

If successful, you should see the container, group5_softwareengineering in Docker.

try at localhost:8000/api/persons


Inserting mock data:

Run Django shell:

docker compose run -it django-web python manage.py shell

Run seed script:

Note that these scripts are normally for fresh databases. There are a few options to seed:

  1. Seed row
exec(open("fango/insert_mock_data.py").read())
  1. Seed multiple rows
exec(open("fango/insert_mock_languages.py").read())
exec(open("fango/insert_mock_data2.py").read())
  1. Seed edge case data
exec(open("fango/insert_test_data.py").read())
run_edge_case_seeding()

Confirm data insert was successful:

Continuing from inside Django shell

  1. Import models (it should have automatically imported anyway) from fango.models
import AppUser, Word, < other table you want to check >
  1. Retrieve all rows from a table in the db, in this case it's AppUser
AppUser.objects.all()
  1. When you're finished:
exit()

From Postgres shell

docker compose exec db psql -U < DATABASE_USERNAME from .env > -d < DATABASE_NAME from .env >
  1. List relations \dt

  2. Take note of schema names, they should be something like fango_appuser, fango_quiz, etc.

  3. You can look at the schema with: \d fango_appuser press q when you're done

  4. Fetch all rows from a table, I'm checking fango_appuser in this example: SELECT * FROM fango_appuser; press q when you're done

  5. When you're finished: exit


Testing Redis Sessioning and Rate Limiting:

docker exec -it fango-redis redis-cli

Show all stored keys

KEYS *

Show all values of a session key, e.g. user::session

HGETALL user:<uid>:session

We use HGETALL because this key is a hash, which is a dictionary stored in Redis

To show number of requests made in the current period of a rate limit key, e.g. ratelimit:<ip/user>:...

GET ratelimit:<ip/user>:...

Show the seconds until a key's expiration

TTL <some key>

Disable rate limiting:

Comment out the RateLimitMiddleware under settings.py

Restarting container to load new changes:

docker restart <container name>

To remove containers and volumes:

docker compose down -v

Frontend Setup

### For frontend updates
rm -rf node_modules package-lock.json pnpm-lock.yaml yarn.lock
npm install
npm run dev

πŸ”§ Environment Variables

Backend (.env)

DJANGO_SECRET_KEY=
DEBUG=
DJANGO_LOGLEVEL=
DJANGO_ALLOWED_HOSTS=

DATABASE_ENGINE=
DATABASE_NAME=
DATABASE_USERNAME=
DATABASE_PASSWORD=
DATABASE_HOST=
DATABASE_PORT=
DATABASE_URL=

TOKEN_SERCRET=

Frontend (.env)

VITE_SERVER_URL=
VITE_REDIRECT_URL=

πŸ—‚οΈ Project Structure

GROUP5_SOFTWAREENGINEERING/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ fango/
β”‚   β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”‚   β”œβ”€β”€ JWTRedisMiddleware.py
β”‚   β”‚   β”‚   └── RateLimitMiddleware.py
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”‚   β”œβ”€β”€ 0001_initial.py
β”‚   β”‚   β”‚   β”œβ”€β”€ 0002_appuser_country_appuser_default_lang_id_and_more.py
β”‚   β”‚   β”‚   └── 0003_appuser_difficulty.py
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   β”œβ”€β”€ mock_response.json
β”‚   β”‚   β”‚   └── openai_service.py
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ tests/
β”‚   β”‚   β”‚   β”œβ”€β”€ test_utils.py
β”‚   β”‚   β”‚   └── test_views.py
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ image_handling/
β”‚   β”‚   β”‚   └── (image helper modules)
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ media/
β”‚   β”‚   β”‚   └── (uploaded images)
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ api_urls.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ asgi.py
β”‚   β”‚   β”œβ”€β”€ insert_mock_data.py
β”‚   β”‚   β”œβ”€β”€ insert_mock_data2.py
β”‚   β”‚   β”œβ”€β”€ insert_mock_languages.py
β”‚   β”‚   β”œβ”€β”€ insert_test_data.py
β”‚   β”‚   β”œβ”€β”€ managers.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ redis_client.py
β”‚   β”‚   β”œβ”€β”€ serializers.py
β”‚   β”‚   β”œβ”€β”€ settings.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   β”œβ”€β”€ utils.py
β”‚   β”‚   β”œβ”€β”€ views.py
β”‚   β”‚   └── wsgi.py
β”‚   β”‚
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ manage.py
β”‚   └── requirements.txt
β”‚
β”‚
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”œβ”€β”€ countries.json
β”‚   β”‚   └── languages.json
β”‚   β”‚
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ assets/
β”‚   β”‚   β”‚   β”œβ”€β”€ pingu_signup.jpg
β”‚   β”‚   β”‚   └── pingu1.jpg
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   β”œβ”€β”€ animation/
β”‚   β”‚   β”‚   β”‚   └── SpringMotionLayout.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ card/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ CardMenu.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Cards.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ GalleryPage.tsx
β”‚   β”‚   β”‚   β”‚   └── ImageFlipCard.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ checkbox/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ MultiCheckbox.tsx
β”‚   β”‚   β”‚   β”‚   └── SingleCheckbox.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ goals/
β”‚   β”‚   β”‚   β”‚   └── options.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ nav/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ AppLayout.tsx
β”‚   β”‚   β”‚   β”‚   └── BottomNav.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   └── utils/
β”‚   β”‚   β”‚       β”œβ”€β”€ AuthRoute.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ CountrySuggest.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ LanguageSuggest.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ PasswordInputStep.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ SuggestInputStep.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ TextInputStep.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ JsonPost.tsx
β”‚   β”‚   β”‚       └── Logout.tsx
β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”‚   β”œβ”€β”€ quickguide/
β”‚   β”‚   β”‚   β”‚   └── QuickGuide.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ quiz/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ DailyQuizDefault.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ DailyQuizResult.tsx
β”‚   β”‚   β”‚   β”‚   └── FavWords.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ signup/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ EmailStep.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ NameStep.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ PasswordStep.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SetUpTargetLan.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SignUp.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SignUpAllSet.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SignupContext.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SignUpDifficulty.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ SignUpGoal.tsx
β”‚   β”‚   β”‚   β”‚   └── Types.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ status/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ 404.tsx
β”‚   β”‚   β”‚   β”‚   └── Loading.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   β”œβ”€β”€ translation/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Camera.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Processing.tsx
β”‚   β”‚   β”‚   β”‚   └── Result.tsx
β”‚   β”‚   β”‚   β”‚
β”‚   β”‚   β”‚   └── user/
β”‚   β”‚   β”‚       β”œβ”€β”€ Login.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ Userhistory.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ Userhistoryitem.tsx
β”‚   β”‚   β”‚       β”œβ”€β”€ Userinfo.tsx
β”‚   β”‚   β”‚       └── Userlearninginfo.tsx
β”‚   β”‚
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ index.html
β”‚   β”œβ”€β”€ package.json
β”‚   β”œβ”€β”€ package-lock.json
β”‚   β”œβ”€β”€ README.md
β”‚   β”œβ”€β”€ tsconfig.json
β”‚   β”œβ”€β”€ tsconfig.app.json
β”‚   β”œβ”€β”€ tsconfig.node.json
β”‚   └── vite.config.ts
β”‚
β”œβ”€β”€ docker-compose.yml
└── README.md

πŸ€– API Workflow

  1. User uploads or snaps a photo

  2. Backend receives image

  3. Image sent β†’ OpenAI Vision

  4. AI returns object description

  5. Backend sends object β†’ GPT model for:

    • Translation into selected language
    • Pronunciation guide
    • Two mini safety-checked phrases
  6. Backend saves both the image + results in PostgreSQL

  7. Frontend displays translation + history updates


πŸ” Authentication

  • JWT (access + refresh) tokens

  • Login / Register endpoints

  • Protected routes:

    • Upload photo
    • View history
    • Manage account

πŸ§ͺ Testing

Backend

python manage.py test

Frontend

npm run test

🧭 Roadmap

  • Offline translation mode
  • Speech recognition (ask questions verbally)
  • AR translation overlay
  • Phrase-of-the-day widget
  • Multi-language phrase packs
  • Dark mode
  • Daily Quiz

πŸ‘₯ Contributors

  • Joe Lin A01079256
  • Louise Li A01377263
  • Blaise Klein A01300754
  • Reece Melnick A01349668
  • Inez Yoon A01066348

About

Members:

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 5