Blog giờ đây đã có song ngữ

Blog giờ đây đã có song ngữ

Tin ngắn hàng ngày dành cho bạn
  • Hơn 1 tuần nay mình không đăng bài, không phải không có gì để viết mà đang tìm cách để phân phối nội dung có giá trị hơn trong thời đại AI đang bùng nổ mạnh mẽ như thế này.

    Như từ hồi đầu năm đã chia sẻ, số lượng người truy cập vào trang blog của mình đang dần ít đi. Khi xem thống kê, lượng người dùng trong 6 tháng đầu năm 2025 đã giảm 30% so với cùng kì năm ngoái, 15% so với 6 tháng cuối năm 2024. Như vậy một sự thật là người dùng đang rời bỏ dần đi. Nguyên nhân do đâu?

    Mình nghĩ lý do lớn nhất là thói quen của người dùng đã thay đổi. Họ tìm thấy blog chủ yếu qua các công cụ tìm kiếm, trong đó lớn nhất là Google. Gần 1/2 số lượng người dùng quay trở lại blog mà không cần thông qua bước tìm kiếm. Đó là một tín hiệu đáng mừng nhưng vẫn không đủ để tăng lượng người dùng mới. Chưa kể giờ đây, Google đã ra mắt tính năng AI Search Labs - tức là AI hiển thị luôn nội dung tổng hợp khi người dùng tìm kiếm, điều đó càng khiến cho khả năng người dùng truy cập vào trang web thấp hơn. Một điều thú vị là khi Search Labs được giới thiệu, thì các bài viết bằng tiếng Anh đã soán ngôi trong bảng xếp hạng truy cập nhiều nhất.

    Một bài viết của mình thường rất dài, có khi lên đến cả 2000 chữ. Mà để viết ra được một bài như thế tốn nhiều thời gian. Nhiều bài viết ra chẳng có ai đọc là điều bình thường. Mình biết và chấp nhận vì không phải ai cũng gặp phải vấn đề đang nói đến. Viết đối với mình như một cách để rèn luyện sự kiên nhẫn và cả tư duy. Viết ra mà giúp được cả ai đó là một điều tuyệt vời.

    Vậy nên mình đang nghĩ sẽ tập trung vào nội dung ngắn và trung bình để viết được nhiều hơn. Nội dung dài chỉ khi muốn viết chi tiết hoặc đi sâu về một chủ đề nào đó. Nên là đang tìm cách thiết kế lại trang blog. Mọi người cùng chờ nha 😄

    » Xem thêm
  • CloudFlare đã giới thiệu tính năng pay per crawl để tính phí cho mỗi lần AI "cào" dữ liệu trên trang web của bạn. Là sao ta 🤔?

    Mục đích của SEO là giúp các công cụ tìm kiếm nhìn thấy trang web. Khi người dùng tìm kiếm nội dung mà có liên quan thì nó hiển thị trang web của bạn ra kết quả tìm kiếm. Điều này gần như là đôi bên cùng có lợi khi Google giúp nhiều người biết đến trang web hơn, còn Google thì được nhiều người dùng hơn.

    Bây giờ cuộc chơi với các AI Agents thì lại khác. AI Agents phải chủ động đi tìm kiếm nguồn thông tin và tiện thể "cào" luôn dữ liệu của bạn về, rồi xào nấu hay làm gì đó mà chúng ta cũng chẳng thể biết được. Vậy đây gần như là cuộc chơi chỉ mang lại lợi ích cho 1 bên 🤔!?

    Nước đi của CloudFlare là bắt AI Agents phải trả tiền cho mỗi lần lấy dữ liệu từ trang web của bạn. Nếu không trả tiền thì tôi không cho ông đọc dữ liệu của tôi. Kiểu vậy. Hãy chờ thêm một thời gian nữa xem sao 🤓.

    » Xem thêm
  • Lúc khái niệm "Vibe Code" bùng nổ mình cũng tò và tìm hiểu xem nó là gì. Hoá ra là chỉ cách lập trình mới: Lập trình viên ra lệnh và để cho LLM tự viết mã. Sau đó là hàng loạt các bài viết nói về cách họ đã xây dựng ứng dụng mà không cần phải viết một dòng mã nào, hoặc 100% là do AI viết...

    Mình không có ý kiến gì vì mỗi người một sở thích. Nhưng nếu tiếp xúc với nhiều thông tin như vậy thì ít nhiều thế hệ lập trình viên mới sẽ "ám ảnh". Khi làm việc với ngôn ngữ lập trình, chúng ta đang tiếp xúc ở bề nổi rồi. Đằng sau đó còn nhiều lớp khác che giấu sự phức tạp. Ví dụ biết viết JavaScript nhưng có biết nó chạy như thế nào không 🤔? Trên thực tế bạn chẳng cần phải biết nó chạy như thế nào mà chỉ cần biết cú pháp là viết được chương trình chạy ngon ơ.

    LLMs giờ đây lại thêm một lớp ảo hoá cho việc viết mã. Tức là nơi chúng ta không cần trực tiếp viết mà là ra lệnh. Làm việc sẽ nhanh hơn nhưng khi gặp vấn đề thì nhiều khả năng phải vận dụng kiến thức của tầng thấp hơn để giải quyết.

    Mình dùng Cursor, nhưng tính năng thích nhất và dùng nhiều nhất là Autocomplete & Suggestions. Thi thoảng cũng dùng Agents để bảo nó viết tiếp đoạn mã đang dở, thường thì nó làm rất tốt. Hoặc khi gặp lỗi thì hỏi, có lúc giải quyết được, lúc thì không. Nhìn chung nó đang làm thay nhiệm vụ của Google & Stack Overflow, giúp tiết kiệm thời gian 😆

    LLMs như một cuốn bách khoa toàn thư rất khủng khiếp. Hỏi gì cũng biết, cũng trả lời được nhưng có một sự thật là nó chỉ là mô hình đoán chữ (đoán tokens). Thế nên nếu vấn đề phổ biến thì nó sẽ làm rất tốt, nhưng vấn đề ít phổ biến hơn thì nó lại rất tệ, hoặc thậm chí là đưa ra thông tin sai lệch, nhiễu... Tóm lại, cần phải biết cách khai thác thông tin, mà để biết thì buộc người dùng phải có một lượng kiến thức nhất định, tránh rơi vào cái bẫy thiên kiến uy quyền (tin tưởng tuyệt đối vào ai đó) hoặc thiên kiến xác nhận (xác nhận niềm tin sẵn có bằng cách chỉ tìm bằng chứng xác nhận niềm tin đó).

    Tại thấy bài viết này nên lại nổi hứng viết vài dòng 🤓 Why I'm Dialing Back My LLM Usage

    » Xem thêm

Vấn đề

Cách đây ít lâu, tôi có tham vấn anh CTO về việc có nên chạy quảng cáo cho Blog để nhiều người biết đến hay không. Anh ấy khựng lại một chút và trả lời “Anh nghĩ là không nên, nếu có thể em hãy thử mở rộng tập người dùng của em ra nước ngoài”. Trước đó, tôi nghĩ rằng mình có thể bỏ tiền ra chạy quảng cáo trên một số nền tảng mạng xã hội để quảng bá blog của mình đến nhiều người hơn, đồng thời tăng lượng truy cập để trang web được ưu tiên hiển thị trong kết quả tìm kiếm. Nhưng qua câu trả lời đó, tôi bỗng nhớ lại dự định từ trước khi viết: “Blog phải có tiếng Anh”.

Nhưng bạn biết đấy, tôi không phải là một người giỏi tiếng Anh, có thể đọc hiểu được một số tài liệu, nhưng mà nói hay viết thì… Đành gác lại toan tính còn dang dở, hy vọng một ngày nào đó có ai dịch bài viết cho mình - Tôi nghĩ.

Rồi bỗng nhiên một ngày ChatGPT xuất hiện, một mô hình ngôn ngữ hiện đại bậc nhất. Nói nôm na là nó có thể hiểu và viết ra câu trả lời như một con người, chứ không đơn thuần là những câu có nghĩa được ghép từ rô-bốt. Nếu nhờ nó dịch bài viết cho mình, khả năng cao văn phong tiếng Anh sẽ trở nên mượt mà hơn so với sử dụng công cụ truyền thống như Google dịch.

Thật ra tôi muốn tích hợp API của ChatGPT vào trang quản trị để nhờ nó dịch trực tiếp bài viết tiếng Việt sang tiếng Anh. Nhưng đợi mãi mà nó vẫn chưa chịu mở API ở khu vực Việt Nam. Không đợi được nữa, tuần vừa rồi là một tuần khá bận rộn khi vừa hoàn thành xong blog đa ngôn ngữ. Vâng, tôi vừa tích hợp thêm i18n cho nó.

Quá trình

Đây không phải là lần đầu tiên tôi làm một trang web hỗ trợ đa ngôn ngữ, trước đó tôi tham gia một số dự án nhưng là xây dựng ngay từ đầu hoặc là tham gia vào quá trình bảo trì, thêm tính năng mới.

2coffee.dev được tạo ra cách đây khá lâu và ngay từ đầu không tích hợp i18n, cho nên cần chút thời gian để nghiên cứu một vài modules hỗ trợ i18n.

Không khó để tìm kiếm, @nuxtjs/i18n là modules phổ biến cho Nuxt.js nên không có lý do gì để không dùng cả. Hãy lướt qua tài liệu để xem cách cài đặt cũng như cấu hình và những gì mà nó làm được.

Sau bước tìm hiểu, tôi bắt tay vào thử nghiệm một số trường hợp để xem cách hoạt động cũng như có đáp ứng được yêu cầu của mình hay không. Ví dụ như làm thế nào để thay đổi ngôn ngữ, có hỗ trợ chuyển ngôn ngữ theo path không (ví dụ /vi là tiếng Việt, /en là tiếng Anh, mặc định / là tiếng Việt chẳng hạn), cấu hình url dẫn đến bài viết khác nhau giữa 2 ngôn ngữ (ví dụ url bài viết hiện tại đang là /bai-viet/ten-bai-viet nhưng khi sang tiếng Anh, tôi muốn nó phải thành /articles/article-title), rồi các liên kết trong trang web cấu hình thế nào để nó trỏ đến đúng url theo ngôn ngữ… rất nhiều thứ cần phải làm.

Và cuối cùng, cái quan trọng nhất là cấu hình SEO cho website đa ngôn ngữ. Phải làm cách nào đó để nói cho các công cụ tìm kiếm biết trang web của mình có nhiều hơn một thứ tiếng, cũng như nội dung tiếng Việt và tiếng Anh của cùng một bài để nó tối ưu kết quả tìm kiếm. Thật may mắn vì trước đó tôi có đọc qua vấn đề này và Google cũng có bài viết rất chi tiết về cách khai báo một website đa ngôn ngữ tại Overview of international and multilingual site topics. Tùy theo trường hợp, ví dụ như tôi đang khai báo địa chỉ sitemap với Google Search Console để họ có thể nhanh chóng cập nhật thông tin, nhưng trước đó sitemap chỉ đang cấu hình một ngôn ngữ, do đó cần cập nhật thêm đa ngôn ngữ.

Tuần vừa rồi, tôi đã gấp rút thực hiện. Bạn thấy đấy, series bài viết về Rust đã bị tạm dừng để tập trung hoàn thiện tính năng song ngữ.

Khó khăn

Mọi chuyện không bao giờ suôn sẻ như những gì mình mong muốn, việc tích hợp song ngữ cũng vậy, thậm chí tôi suýt phải bỏ dở vì một lỗi khó hiểu vào phút chót.

Do không tích hợp i18n ngay từ đầu cho nên phải đi tìm lại những nơi có ngôn ngữ hiển thị ở trong code, đưa nó vào các tệp cấu hình ngôn ngữ, dịch nó và thay thế bằng mã hỗ trợ hiển thị ngôn ngữ của module i18n.

Vấn đề mất nhiều thời gian nhất là tích hợp đường dẫn trong thẻ <nuxt-link>, cụ thể là props to. Thông thường chúng ta sử dụng <nuxt-link to=“/path”> để tạo liên kết đến router /path. Nhưng như tôi đã nói, đường đẫn đến bài viết giữa 2 ngôn ngữ Việt/Anh là khác nhau, cho nên phải sử dụng cú pháp mới: <nuxt-link :to="localePath({ name: 'bai-viet-id', params: { id: article.url } })”>. Cấu trúc trong localePath bao gồm name là tên đường dẫn, params để khai báo params trong url đến liên kết mới. Để dễ hình dung, hãy nhìn vào cấu trúc thư mục hiện tại của tôi:

Cấu trúc thư mục

Oh, vậy thì name phải là bai-viet thôi chứ sao lại là bai-viet-id. Vâng điều đó tiêu tốn kha khá thời gian của tôi để tìm ra cách làm thế khai báo router có chứa params, cụ thể ở đây là _id.

Đến đây mọi thứ đã gần như xong xuôi cả rồi, đến bước npm run generate để tạo trang web static thì nhiều lỗi lại xuất hiện, mọi nỗ lực lúc này là cố gắng “fix” chúng. Nếu như sử dụng SSR thì nhiều vấn đề trở nên đơn giản hơn nhưng tôi lựa chọn SSG để tăng tốc độ tải trang, SSG có cách xây dựng mã khác so với SSR nên cần sửa lại mã tương thích với nó.

Cuối cùng, tưởng rằng mọi thứ đã sẵn sàng để deploy rồi thì khi kiểm tra lại, tôi phát hiện ra ở lần tải đầu tiên, trang web của tôi bị vỡ giao diện trong khoảng thời gian rất ngắn, dù chỉ là nhấp nháy rất nhỏ nhưng nếu để ý sẽ thấy rất khó chịu, chưa kể điều này còn khiến công cụ tìm kiếm đánh giá thấp về mặt hiệu năng.

Nếu như nhiều lỗi khác có để để lại thông báo rõ ràng về nguyên nhân cũng như vị trí lỗi, thì với lỗi giao diện điều đó là quá xa xỉ. Tôi tin chắc nhiều người rơi vào trạng thái này và tuyệt vọng trong vấn đề suy đoán lỗi ở đâu. Riêng tôi thì checkout lại về từng commit để xem vấn đề bắt đầu từ chỗ nào. Quả không sai, nó xuất hiện từ commit thêm cấu hình module i18n.

Quái dị, i18n thì liên quan gì đến giao diện chứ? Tôi cũng nghĩ vậy, mất rất nhiều thời gian để tìm kiếm câu trả lời trên mạng nhưng hình như không có ai bị cả, chắc mình cần tạo một issue về vấn đề này trên Github? Hmm… có lẽ sẽ mất nhiều thời gian, chưa kể cần trình bày lại cấu trúc dự án lẫn vấn đề đang gặp phải để đợi người khác trả lời? ==‘

Đành phải tự thân vận động thôi, tôi debug sự khác nhau giữa 2 commit trước và sau khi thêm module i18n và phát hiện ra một dữ kiện, ở commit sau khi thêm module, có một file css được tải chậm hơn, nó cũng chính là css của thành phần vỡ giao diện, tiếp tục xem tại sao nó lại bị tải chậm hơn thì hóa ra, nó được thực thi sau khi một file js được tải xuống, hay nói cách khác, file js đó chứa đoạn mã tải xuống css. Vậy có nghĩa là module i18n đang cố thay đổi cấu trúc dự án build ra!?

Tôi mò đến cấu hình build trong file nuxt.config.js, có một options đang bật là:

build: {
    …
    extractCSS: {
      ignoreOrder: true,
    },
}

Đây là tùy chọn tách các file css thành các file nhỏ hơn để tăng tốc độ tải, có lẽ việc tách css đã xung đột với i18n, khiến nó suy nghĩ file css kia không quan trọng và có thể tải sau cho nên dẫn đến giao diện bị vỡ trong một khoảng thời gian ngắn. Tôi tắt tùy chọn đấy đi thì… mọi thứ đã hoạt động trở lại. Thật may mắn!

Tiếp theo

Bước đầu là việc viết mã, sau đó là một hành trình dài.

Trước tiên, tôi sẽ nhờ ChatGPT dịch một số bài mà cảm thấy có thể dịch được sang tiếng Anh, sửa lại vài thứ như định dạng, hình ảnh… bởi vì tôi có thử dịch một bài nhưng nó không trả về định dạng markdown để cho mình copy được. Một số bài viết có định dạng mã trong các dấu nháy ngược (`), khi hiển thị trong ChatGPT thì bị lỗi… tóm lại, sau khi nhờ dịch, vẫn cần phải chỉnh sửa lại nhiều trước khi xuất bản bài viết hoàn chỉnh.

Đánh giá hiệu quả của việc SEO cũng như sửa lỗi hay vấn đề phát sinh sau này, bởi vì tôi chưa có nhiều kinh nghiệm về việc quản lý website đa ngôn ngữ.

Tuy là dịch, nhưng tôi sẽ cố gắng đọc lại bài viết đã dịch và hy vọng sẽ học hỏi thêm được nhiều điều thông qua cách này!

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Ẩn danh11 tháng trước

chào bạn có thể hướng dẫn rõ hơn về cách cài đặt đa ngôn ngữ cho blog không ạ?

Trả lời