Trong bài viết này sẽ hướng dẫn xây dựng một màn hình đăng nhập đơn giản và hỗ trợ đa ngôn ngữ (tiếng Anh và tiếng Việt) bằng cách sử dụng HTML, Thymeleaf, Bootstrap

1. Tổng Quan Về Dự Án

Màn hình đăng nhập mà chúng ta sẽ tạo có các tính năng sau:

  • Giao diện thân thiện với người dùng, sử dụng Bootstrap để tạo bố cục responsive.
  • Hỗ trợ đa ngôn ngữ (tiếng Anh và tiếng Việt) thông qua Thymeleaf.
  • Xử lý lỗi đăng nhập (hiển thị thông báo nếu thông tin đăng nhập không hợp lệ).
  • Tự động chuyển hướng đến trang chủ nếu người dùng đã đăng nhập (kiểm tra qua cookie accessToken).

Cấu trúc thư mục của dự án như hình sau:

hình ảnh_2025-03-20_123756899.png

2. Tạo một trang HTML cơ bản


- Tạo một file user-login.html với cấu trúc cơ bản
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="#{login}">Login</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
    <!-- Nội dung sẽ được thêm vào đây -->
</body>
</html>

- <!DOCTYPE html>: Khai báo đây là tài liệu HTML5.

- xmlns:th: Thêm namespace cho Thymeleaf, một công cụ giúp hiển thị dữ liệu động.

- Bootstrap: Sử dụng CDN của Bootstrap 5.3.3 để tạo giao diện mà không cần viết quá nhiều CSS.

- styles.css: File CSS tùy chỉnh.

3. Tạo form đăng nhập

Phần chính của màn hình là form đăng nhập. Đặt nó trong một container Bootstrap để căn giữa:

<div class="container container-custom">
    <h2 class="heading-login" th:text="#{login}">Login</h2>
    <form action="/login" method="post">
        <div class="mb-3">
            <label for="username" class="form-label" th:text="#{username}">Username</label>
            <input type="text" class="form-control" id="username" name="username"
                   th:placeholder="#{username.placeholder}" required>
        </div>
        <div class="mb-3">
            <label for="password" class="form-label" th:text="#{password}">Password</label>
            <input type="password" class="form-control" id="password" name="password"
                   th:placeholder="#{password.placeholder}" required>
        </div>
        <button type="submit" class="btn btn-primary btn-full-width" th:text="#{login.button}">Login</button>
    </form>
</div>

- container: Lớp Bootstrap giúp căn giữa nội dung.

- th:text: Lấy dữ liệu từ file ngôn ngữ.

- required: Đảm bảo người dùng phải nhập thông tin trước khi gửi form.

- method="post": Dữ liệu sẽ được gửi qua phương thức POST tới endpoint /login.

4. Thêm hỗ trợ đa ngôn ngữ


- Để người dùng có thể chuyển đổi giữa tiếng Việt và tiếng Anh, thêm phần sau ngay trên form:
<div class="language-switcher">
    <a th:href="'/login?lang=vi'" th:text="#{login.language.vi}">Vietnamese</a> |
    <a th:href="'/login?lang=en'" th:text="#{login.language.en}">English</a>
</div>
- th:href: Tạo liên kết động để thay đổi ngôn ngữ bằng cách thêm tham số lang vào URL.
- th:text: Hiển thị "Username" hoặc "Tên người dùng" dựa trên file ngôn ngữ.

- Cần cấu hình file ngôn ngữ.

File messages_en.properties:

login=Login
username=Username
username.placeholder=Enter your username
password=Password
password.placeholder=Enter your password
login.button=Login
login.language.en=English
login.language.vi=Tiếng Việt
login.error=Invalid username or password
File messages_vi.properties:
login=Đăng nhập
username=Tên người dùng
username.placeholder=Nhập tên người dùng
password=Mật khẩu
password.placeholder=Nhập mật khẩu
login.button=Đăng nhập
login.language.en=English
login.language.vi=Tiếng Việt
login.error=Tên người dùng hoặc mật khẩu không đúng
Lưu ý: Khi bị lỗi phông chữ Tiếng Việt vào Setting chọn File Encodings tích vào Transparent native-to-ascii conversion và chọn Apply hình ảnh_2025-03-20_125052425.png

5. Hiển thị thông báo lỗi

  • Nếu thông tin đăng nhập bị sai sẽ hiện thông báo lỗi:
<div th:if="${error}" class="alert alert-danger error-message" th:text="#{login.error}">
    Invalid username or password
</div>
- th:if="${error}": Chỉ hiển thị khi biến error tồn tại (do backend gửi).
- alert alert-danger: Lớp Bootstrap tạo hộp thông báo màu đỏ.

6. Tự động chuyển hướng nếu đã đăng nhập

  • Để kiểm tra xem người dùng đã đăng nhập chưa dùng JavaScript để đọc cookie
<script>
    function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
        return null;
    }

    const accessToken = getCookie("accessToken");
    if (accessToken != null && accessToken !== '') {
        window.location.href = '/home';
    }
</script>
- getCookie: Hàm lấy giá trị của cookie theo tên.
- accessToken: Nếu cookie accessToken tồn tại, chuyển hướng người dùng tới trang /home.

- Thêm script Bootstrap để hỗ trợ các thành phần giao diện.
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

7. Tùy chỉnh giao diện

  • Tạo file styles.css để tùy chỉnh thêm.
.container-custom {
    max-width: 600px;
    margin-top: 5rem;
    margin-left: auto;
    margin-right: auto;
}

.language-switcher {
    margin-bottom: 1rem;
    text-align: right;
}

.heading-login {
    text-align: center;
    margin-bottom: 1.5rem;
}

.btn-full-width {
    width: 100%;
}

.error-message {
    margin-top: 1rem;
    text-align: center;
}
- .container-custom: Giới hạn chiều rộng của form và căn giữa.
  • .heading-login: Căn giữa tiêu đề "Login".
  • .btn-full-width: Nút "Login" chiếm toàn bộ chiều rộng.
  • .error-message: Khoảng cách cho thông báo lỗi.
  • .language-switcher: Căn phải các liên kết chuyển đổi ngôn ngữ.
  • Lưu ý: thêm resources.enable=true vào file application.properties

8. Cách Hoạt Động Của Màn Hình Đăng Nhập

Hiển thị giao diện: Khi người dùng truy cập /login, file user-login.html sẽ được render. Tiêu đề, nhãn, placeholder và nút sẽ hiển thị theo ngôn ngữ được chọn (mặc định là tiếng Anh nếu không có tham số lang).

Chuyển đổi ngôn ngữ: Người dùng có thể nhấp vào liên kết "Vietnamese" hoặc "English" để thay đổi ngôn ngữ. Tham số lang trong URL sẽ được gửi đến server, và Thymeleaf sẽ tải file ngôn ngữ tương ứng.

Xử lý đăng nhập: Khi người dùng nhập username và password rồi nhấn "Login", form sẽ gửi dữ liệu đến endpoint /login (phương thức POST). Server sẽ kiểm tra thông tin đăng nhập:

  • Nếu thành công, server tạo cookie accessToken và chuyển hướng người dùng đến /home.
  • Nếu thất bại, server trả về biến error (giá trị true), và thông báo lỗi sẽ hiển thị.

Tự động chuyển hướng: Nếu cookie accessToken đã tồn tại (nghĩa là người dùng đã đăng nhập), JavaScript sẽ tự động chuyển hướng đến /home.

Đây sẽ là giao diện của màn hình đăng nhập vừa tạo (bằng cách truy cập localhost:8080/login)

hình ảnh_2025-03-13_095043250.png

9. Tóm lại

Trên đây là cách tạo một màn hình login đơn giản. Hy vọng với những chia sẻ trên đây giúp bạn nắm được đặc điểm và ứng dụng.

Bạn có thể tìm hiểu kỹ hơn về phần souce code tại đây.